synchronized
原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap
)。我们可以进一步研究ReentrantLock
的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState
。这里其实就是调用的CPU提供的特殊指令。
现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet()
就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。
锁的类型:synchronized:可重入,不可中断,非公平Lock:可重入,可判断,可公平(两者皆可) 性能区别:synchronized 是托管给JVM 执行的,而lock 是java 写的控制锁的代码。 lock 性能更高些。 synchronized 原始采用的是CPU 悲观锁机制,即线程获得的是独占锁。 Lock锁底层调用了cpu提供的CAS原子指令,
CAS(乐观锁) CAS 全称为Compare And Swap 翻译过来就是比较并且交换的意思 @adolph CAS的全称为Compare And Swap,直译就是比较交换。 是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在intel的CPU中,使用的是cmpxchg指令,就是说CAS是靠硬件实现的,从而在硬件层面提升效率。 不过,cas存在ABA问题 @vic J.U.C 包提供了一个带有时间戳的原子引用类 AtomicStampedReference 来解决该问题,它通过控制变量的版本来保证 CAS 的正确性。 @vic 用过cas,没怎么遇到过aba问题 @adela 一般情况下,数值型并发修改不会出现aba问题,但是引用型并发修改则会出现aba问题,导致出现非预期结果
https://zhuanlan.zhihu.com/p/413919463