Java多线程synchronized同步失效两线程输出相同num值原因咨询
并发异常原因
该异常的核心诱因是synchronized锁未实现全局互斥,加锁逻辑完全失效,具体逻辑如下:
- 你定义的锁对象
obj是sell_ticket类的实例成员变量,没有加static修饰。当你实例化s1、s2两个sell_ticket对象时,两个实例会各自生成独立的obj对象,两个线程持有的锁是完全无关的两个对象。 - synchronized的互斥生效前提是:多个竞争访问共享资源的线程,必须争抢同一个锁对象,同一时间才会只有一个线程进入同步代码块。现在s1加锁用的是自身持有的obj,s2加锁用的是自身持有的obj,两个锁互不干扰,两个线程可以同时进入同步块操作共享的静态变量
num,自然会出现同时读到num=0、重复打印0的问题。
修复方案
只需要保证所有线程访问共享变量num时,争抢的是同一个全局唯一锁即可,两种常用实现:
- 将锁对象改为类级别的静态成员,所有
sell_ticket实例共用同一个锁对象
static int num = 0; // 给obj添加static修饰,全类共享唯一实例 static Object obj = new Object(); @Override public void run() { while(true){ synchronized (obj){ if(num < 10000){ System.out.println("sell ticket " + this.getName() + " " + this.num); num ++; } else break; } } }
- 直接使用类的Class对象作为锁,JVM加载类时生成的Class对象是全局唯一的
static int num = 0; @Override public void run() { while(true){ // 锁使用当前类的Class对象 synchronized (sell_ticket.class){ if(num < 10000){ System.out.println("sell ticket " + this.getName() + " " + this.num); num ++; } else break; } } }
注意:你的代码中
num是静态成员,属于类级别的共享资源,所有对该资源的读写操作都必须处于同一把锁的保护下,否则同步逻辑不会产生任何互斥效果。
内容的提问来源于stack exchange,提问作者吕泓瑾
相关产品推荐
相关产品推荐

