Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 375|回复: 0

多线程解决同步问题浅析

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-6-15 15:13:14 | 显示全部楼层 |阅读模式

    一,问题背景

    1.为什么要引入多线程?

         用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”。

    2.多线程、同步、并发概念:

    多线程:指的是这个程序(一个进程)运行时产生了不止一个线程。
    并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
    并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

    3.引入多线程后会带来那些问题?

          java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。

    以买票系统为例,我们发现不加控制多线程会出现超卖现象。

     1 public class RunnableImpl implements Runnable {
     2 
     3 private int ticket=100;
     4     @Override
     5     public void run() {
     6         while(true){
     7             if (ticket<=0){
     8                 break;
     9             }
    10             try {
    11                 Thread.sleep(200);
    12                 String name = Thread.currentThread().getName();
    13                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    14             } catch (InterruptedException e) {
    15                 e.printStackTrace();
    16             }
    17 
    18         }
    19 
    20 
    21 
    22     }
    23 }

    测试类:

    1 public class originticket {
    2     public static void main(String[] args) {
    3         RunnableImpl runnable = new RunnableImpl();
    4        new Thread(runnable,"一").start();
    5        new Thread(runnable,"二").start();
    6     }
    7 }

     

    结果显示:

     

    二,问题解决方案之synchronize代码块:

     1 public class RunnableImplsyn implements Runnable {
     2 
     3 private int ticket=200;
     4     @Override
     5     public void run() {
     6         while(true) {
     7             try {
     8                 Thread.sleep(200);
     9             } catch (InterruptedException e) {
    10                 e.printStackTrace();
    11             }
    12             synchronized (this) {
    13             if (ticket <= 0) {
    14                 break;
    15             }
    16 
    17 
    18                     String name = Thread.currentThread().getName();
    19                     System.out.println("第" + name + "窗口正在卖出第" + (200 - ticket + 1) + "张票,剩余" + (--ticket) + "张");
    20 
    21 
    22             }
    23         }
    24 
    25 
    26     }
    27 }

    测试类:

    1 public class synchronizeblockTicket {
    2 
    3     public static void main(String[] args) {
    4         RunnableImplsyn runnableImplsyn = new RunnableImplsyn();
    5         new Thread(runnableImplsyn,"一").start();
    6         new Thread(runnableImplsyn,"二").start();
    7     }
    8 }

    结果:

    三,问题解决方案之synchronize方法:

    这里抽取了方法,this代指:

     1 public class RunnableImplsynfn implements Runnable {
     2 
     3 private static int ticket=200;
     4     @Override
     5     public void run() {
     6        test();
     7    
     8     }
     9 
    10 
    11     private synchronized void test() {
    12         while(true){
    13             if (ticket<=0){
    14                 break;
    15             }
    16             try {
    17                 Thread.sleep(200);
    18                 String name = Thread.currentThread().getName();
    19                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    20             } catch (InterruptedException e) {
    21                 e.printStackTrace();
    22             }
    23 
    24         }
    25 
    26 
    27 
    28     }
    29     }

    测试类:

    1 public class synchronizefnTicket {
    2 
    3 
    4     public static void main(String[] args) {
    5         RunnableImplsynfn runnableImplsyn = new RunnableImplsynfn();
    6         new Thread(runnableImplsyn,"一").start();
    7         new Thread(runnableImplsyn,"二").start();
    8     }
    9 }

    四,问题解决方案之静态synchronize方法:

    同上

     1 public class RunnableImplsynfn implements Runnable {
     2 
     3 private static int ticket=200;
     4     @Override
     5     public void run() {
     6         statictest();
     7 
     8     }
     9 
    10     private static synchronized void statictest() {
    11         while(true){
    12             if (ticket<=0){
    13                 break;
    14             }
    15             try {
    16                 Thread.sleep(200);
    17                 String name = Thread.currentThread().getName();
    18                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    19             } catch (InterruptedException e) {
    20                 e.printStackTrace();
    21             }
    22 
    23         }
    24 
    25     }
    26    
    27 
    28     }
    29     }

    测试类一样略。

    五,问题解决方案之lock方法:

     1 import java.util.concurrent.locks.Lock;
     2 import java.util.concurrent.locks.ReentrantLock;
     3 
     4 public class Runnablelock implements Runnable {
     5     private int ticket=200;
     6    Lock l= new ReentrantLock();
     7 
     8     @Override
     9     public void run() {
    10         while(true){
    11  /*       try {
    12         Thread.sleep(20);
    13         } catch (InterruptedException e) {
    14             e.printStackTrace();
    15         }*/
    16 l.lock();//从此以后加锁
    17 
    18             if (ticket<=0){
    19                 break;
    20             }
    21             try {
    22                 Thread.sleep(200);
    23 
    24                 String name = Thread.currentThread().getName();
    25                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    26             } catch (InterruptedException e) {
    27                 e.printStackTrace();
    28             }finally {
    29                 l.unlock();//释放锁
    30             }
    31 
    32         }
    33 
    34 
    35     }
    36 }

    测试类:

    1 public class lockTicket {
    2 
    3 
    4     public static void main(String[] args) {
    5         Runnablelock runnablelock = new Runnablelock();
    6         new Thread(runnablelock,"一").start();
    7         new Thread(runnablelock,"二").start();
    8     }
    9 }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-2 04:42 , Processed in 0.064652 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表