拓展阅读:

通过一个卖票的小案例来看,比如大家去抢dota2 ti9门票,如果不加锁的话会出现什么问题?此时代码如下:

复制代码
package Thread;  import java.util.concurrent.TimeUnit;  public class Ticket {      /**      * 初始库存量      * */     Integer ticketNum = 8;      public void reduce(int num){         //判断库存是否够用        if((ticketNum - num) >= 0){             try {                 TimeUnit.MILLISECONDS.sleep(200);             }catch (InterruptedException e){                 e.printStackTrace();             }             ticketNum -= num;             System.out.println(Thread.currentThread().getName() + "成功卖出"            + num + "张,剩余" + ticketNum + "张票");         }else {             System.err.println(Thread.currentThread().getName() + "没有卖出"                    + num + "张,剩余" + ticketNum + "张票");         }     }      public static void main(String[] args) throws InterruptedException{         Ticket ticket = new Ticket();         //开启10个线程进行抢票,按理说应该有两个人抢不到票        for(int i=0;i<10;i++){             new Thread(() -> ticket.reduce(1),"用户" + (i + 1)).start();         }         Thread.sleep(1000L);     }  }
复制代码

 

代码分析:这里有8张ti9门票,设置了10个线程(也就是模拟10个人)去并发抢票,如果抢成功了显示成功,抢失败的话显示失败。按理说应该有8个人抢成功了,2个人抢失败,下面来看运行结果:

我们发现运行结果和预期的情况不一致,居然10个人都买到了票,也就是说出现了线程安全的问题,那么是什么原因导致的呢?

原因就是多个线程之间产生了时间差

如图所示,只剩一张票了,但是两个线程都读到的票余量是1,也就是说线程B还没有等到线程A改库存就已经抢票成功了。

怎么解决呢?想必大家都知道,加个synchronized关键字就可以了,在一个线程进行reduce方法的时候,其他线程则阻塞在等待队列中,这样就不会发生多个线程对共享变量的竞争问题。

举个例子

比如我们去健身房健身,如果好多人同时用一台机器,同时在一台跑步机上跑步,就会发生很大的问题,大家会打得不可开交。如果我们加一把锁在健身房门口,只有拿到锁的钥匙的人才可以进去锻炼,其他人在门外等候,这样就可以避免大家对健身器材的竞争。代码如下:

复制代码
public  synchronized void reduce(int num){         //判断库存是否够用        if((ticketNum - num) >= 0){             try {                 TimeUnit.MILLISECONDS.sleep(200);             }catch (InterruptedException e){                 e.printStackTrace();             }             ticketNum -= num;             System.