Java中synchronized锁Integer类型count失效但锁this正常问题咨询
问题原因分析
两种锁对象的核心差异
- 锁为
this的场景:你代码中两个线程t1、t2共享同一个Multi类实例r1,this始终指向这个唯一的r1实例,所有线程竞争的是同一个固定锁对象,因此同步块可以保证每次只有一个线程进入修改count,最终累加结果正确为200000。 - 锁为
Integer count的场景:Integer是不可变类,类内存储数值的value字段被final修饰,无法修改。你写的count++本质是三步操作:先将Integer拆箱为int值、执行+1计算、再自动装箱为新的Integer对象赋值给count变量。也就是说每执行一次count++,count指向的对象就会更新为新的实例,锁对象全程在动态变化,两个线程竞争的不是同一个锁,同步逻辑自然失效。
同步失效的具体执行逻辑
举个简单的执行序列说明:
线程1首先获取到当前
count(值为10)的对象锁,进入同步块执行count++,执行结束后count指向了值为11的新Integer对象,随后线程1释放的是旧的、值为10的对象锁;此时线程2尝试获取锁,直接拿到了新的、值为11的对象锁,完全不会被线程1的旧锁阻塞,两个线程就会出现同时修改count的情况,累加操作出现丢失更新,最终结果就是不符合预期的随机值。
可行的修复方案
- 方案1:保留注释中的
this作为锁对象,锁实例全程固定,可保证同步有效性。 - 方案2:定义专用的不可变锁对象,是行业推荐的最佳实践,代码示例如下:
class Multi extends Thread { Integer count = new Integer(0); // 定义专用的final锁对象,不会被修改 private final Object lock = new Object(); @Override public void run() { for(int i=0;i<100000;i++) { synchronized (lock) { count++; } } System.out.println(Thread.currentThread().getName() + " "+count); } }
- 方案3:直接使用JUC包下的原子类
AtomicInteger实现累加,不需要额外加同步锁,性能更高:
class Multi extends Thread { AtomicInteger count = new AtomicInteger(0); @Override public void run() { for(int i=0;i<100000;i++) { count.incrementAndGet(); } System.out.println(Thread.currentThread().getName() + " "+count.get()); } }
内容的提问来源于stack exchange,提问作者satya sai
相关产品推荐
相关产品推荐

