空synchronized代码块为何影响程序输出结果?
为什么空的
synchronized代码块能让线程输出同步? 嘿,这个问题问得特别戳中并发编程的核心细节——很多刚摸并发的同学都会被这个“空块生效”的现象搞懵,其实本质和代码块里有没有内容完全没关系,关键在于synchronized本身的锁机制。
先搞懂synchronized到底在做什么
synchronized的核心作用从来不是执行代码块里的逻辑,而是通过对象的内置锁(Intrinsic Lock,也叫监视器锁)实现线程间的互斥与同步:
- 当线程要进入
synchronized(锁对象)代码块时,必须先成功获取这个锁对象的内置锁; - 同一时间,只有一个线程能持有这个锁——如果锁已经被其他线程占了,当前线程就会进入阻塞状态,直到锁被释放;
- 不管是正常退出代码块,还是因为异常退出,线程都会自动释放持有的锁。
回到你的场景:空块为什么能同步输出?
从你给出的代码片段来看,主线程和SyncTest线程应该都在竞争同一个锁对象f(主线程里是synchronized(f),SyncTest的run方法里大概率也有同样的synchronized(f)块)。
哪怕这个块里是空的,只要两个线程都在尝试获取同一个锁,就会触发互斥执行:
- 比如主线程先执行到
synchronized(f),成功拿到锁,然后退出块释放锁; - 这时候
SyncTest线程才能拿到锁,执行它的输出逻辑,之后退出块释放锁; - 反过来,
SyncTest线程持有锁时,主线程会卡在synchronized(f)的入口,直到锁被释放才能继续输出。
相当于这个空的synchronized块成了两个线程的“执行闸门”——强制它们必须交替获取锁,从而让输出不会出现杂乱的交替,看起来像是同步的。
额外提醒:别随便用空synchronized块
虽然它能实现同步,但这是一种非常不规范的写法:
- 可读性极差,其他开发者看到空块会完全摸不着头脑;
- 容易引发误解,甚至可能因为锁对象的选择不当导致隐藏的并发问题;
- 如果是为了线程间的顺序控制,更推荐用
CountDownLatch、CyclicBarrier这类专门的同步工具,或者明确保护共享资源的访问逻辑。
内容的提问来源于stack exchange,提问作者SpongeBoobies
相关产品推荐
相关产品推荐

