为什么说 Synchronized 是一个悲观锁?
Synchronized 是一个悲观锁,主要基于以下原因:
- 独占性:当一个线程获得了对象的 Synchronized 锁时,其他线程必须等待该线程释放锁后才能继续执行,这体现了悲观锁对资源的独占性。
- 悲观假设:Synchronized 锁的使用基于悲观锁的思想,即默认认为每次访问共享资源时都会发生冲突。因此,它采用加锁的方式来确保同一时间只有一个线程能够访问共享资源,从而避免潜在的竞争和冲突。
乐观锁的实现原理
乐观锁的实现原理基于以下核心思想:
- 无锁竞争:乐观锁假设在大多数情况下,多个线程之间不会发生冲突。因此,它允许多个线程同时读取数据,但在更新数据时需要进行额外的检查。
- 版本控制:乐观锁通常通过版本号或时间戳来实现并发控制。在更新数据时,线程会检查数据的版本号或时间戳是否与预期一致。如果一致,说明在读取数据到更新数据的这段时间内没有其他线程修改过数据,因此可以安全地进行更新;如果不一致,则说明数据已被其他线程修改,此时更新操作会失败,线程需要重新读取数据并尝试更新。
什么是 CAS?
CAS(Compare-And-Swap)是一种用于实现无锁并发控制的原子操作。
CAS 的特性
CAS 具有以下特性:
- 原子性:CAS 操作是原子的,这意味着它是不可分割的。在执行 CAS 操作的过程中,不会被其他线程或中断打断。
- 非阻塞性:CAS 操作是一种非阻塞同步机制。如果 CAS 操作失败,线程不会进入阻塞状态,而是可以立即重试。
- 依赖于硬件支持:CAS 操作通常由处理器提供的原子指令来实现,如 x86 架构中的 CMPXCHG 指令。
- 可见性:在进行 CAS 操作之前,必须先获取对象的锁(尽管这个锁通常是轻量级的,并且不会阻塞其他线程),这确保了对象的比较和交换操作是可见的。
- 有限重试:在高并发场景下,CAS 操作可能会由于竞争失败而需要多次重试。然而,由于 CAS 操作本身开销较小,因此即使需要多次重试,通常也不会对性能产生太大影响。
综上所述,Synchronized 是一个悲观锁,因为它默认认为每次访问共享资源时都会发生冲突并采取加锁的方式来确保线程安全;而乐观锁则基于无锁竞争和版本控制的原理来实现并发控制;CAS 是一种用于实现无锁并发控制的原子操作,具有原子性、非阻塞性、依赖于硬件支持、可见性和有限重试等特性。