Java中synchronized关键字未实现预期线程同步效果的问题
问题原因与解决方法
问题根源
你代码中的synchronized修饰的是非静态方法func(),此时锁的是当前对象实例。但你创建了两个Runner对象(r1和r2),两个线程分别持有各自对象的锁,对静态变量cnt的操作无法互斥,因此会出现线程安全问题,导致最终结果小于20000。
解决方法
方法1:将同步方法改为静态同步方法
静态同步方法的锁是类对象(Runner.class),所有线程共享这个锁,能保证对静态变量cnt的原子性操作:
public static synchronized void func() { cnt++; }
方法2:在非静态方法中使用类对象作为锁
如果不想修改方法的静态属性,可以在方法内部同步类对象:
public void func() { synchronized(Runner.class) { cnt++; } }
方法3:使用同一个对象实例启动线程
只创建一个Runner实例,用两个Thread包装它,这样两个线程共享同一个对象锁:
public class Synchronization { public static void main(String[] args) { Runner runner = new Runner(); Thread r1 = new Thread(runner); Thread r2 = new Thread(runner); r1.start(); r2.start(); try { r1.join(); r2.join(); } catch (InterruptedException e) { e.printStackTrace(); } runner.print(); } }
注:更规范的做法是让Runner实现Runnable接口而非继承Thread,但上述调整可适配原代码逻辑。
关键说明
静态变量属于类级别资源,只有当同步操作基于类锁或共享的对象锁时,才能保证多个线程对它的操作是线程安全的。
内容的提问来源于stack exchange,提问作者Rohit Godara
相关产品推荐
相关产品推荐

