别再"报菜名"了,用一条逻辑链路带你搞定 Synchronized 和 Lock 的区别

网上各种推文和博客都自说自话的的教人不要去背八股文,要去理解八股文,真要讲解起自己的内容了,又在自顾自的报菜名,把一堆离散的特性罗列出来,几乎没有逻辑性,想到哪一点说哪一点,就像这个八股文题目一样,至少能答出来五条.这五条每条都是分开的特性,没有内在联系,逻辑性也微乎其微,所以我以为,这种繁琐的八股文,首先要在最开始时就创建一条便于记忆的逻辑链路,不要太依赖于自己的离散记忆,这是不可靠且不稳定的(起码对我来说)

我觉得这种繁琐的八股文,最稳妥的方法是在最开始就创建一条便于记忆的逻辑链路。别依赖那种不稳定的离散记忆,咱得按锁的"一生"把这些点串起来。

  1. 先从语法切入(出身决定了怎么释放)

    首先看出身。synchronized 是由 JVM 控制的关键字,而 Lock 是 JDK 层面的一个接口。因为出身不同,管理方式就变了:

    Synchronized 既然是 JVM 管的,它就很智能,一旦代码出异常了,JVM 会自动帮你把锁给放了。

    Lock 是 JDK 层面的,它是"人工"的,所以你得显式地去释放。通常都要写在 finally 块里手动执行 unlock(),不然锁就死在那儿了。

  2. 核心特性(分配规则)

    有了出身,再看它们的"性格",也就是公平性。

    Synchronized 比较霸道,它是非公平锁,新来的线程可以直接插队。

    Lock 就很灵活,它既支持非公平锁,也支持公平锁(可以在构造的时候传参数实现)。

  3. 锁的使用周期(获取、唤醒、中断)

    最后咱们看这个锁从"开始拿"到"中间等"再到"被唤醒"的整个操作逻辑,这才是最体现差距的地方:

    锁的获取: synchronized 只有一种姿势,就是线程阻塞在那死等。而 Lock 可以通过 tryLock 进行非阻塞获取,拿不到我就干别的去,甚至还能设置个超时时间。

    锁的中断: synchronized 不支持中断,一旦等上了谁也劝不动。但 Lock 可以通过 lockInterruptibly 响应中断,等烦了是可以撤回的。

    锁的唤醒: synchronized 配合 notify/notifyAll 只能乱扣或者全喊。而 Lock 配合 Condition 可以实现精准唤醒,我想叫醒哪一类线程就叫醒哪一类。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐