Skip to content

Latest commit

 

History

History
32 lines (23 loc) · 3.12 KB

cashe-synchronized-de-bi-jiao.md

File metadata and controls

32 lines (23 loc) · 3.12 KB
对比项 同步锁(synchronized) 比较和替换(CAS机制)
是否线程安全 可以保证线程安全 可以保证线程安全
是否为原子性操作 原子性操作:synchronized( Xxx.class ) { 代码语句 } 原子性操作:一系列以Atomic开头的包装类,boolean,integer,Long
性能表现 会有性能问题。 性能要比synchronized要好,但是也不绝对,任何机制都没有绝对的好与坏,在已知的并发量很高的情况下,同步锁反而比CAS要好。
原理 1. CAS机制中使用了3个基本的操作数:内存地址V,旧的预期值A,新的修改值B。更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
2. 先比对地址是否一样,如果一样,把旧的替换成新的。
3. 如果地址不相等(存在被其他的线程抢先一步修改的情况,这种内存地址不相等的情况下会重新获取期望值,并且重新计算新的修改值,这个重新计算的过程称为自旋)。
设计思想 悲观锁 乐观锁
Java中的应用 Java中用的原子性操作的包:Atomic系列类、Lock系列类
缺点 会让没有得到锁资源的线程进入被阻塞状态,在争夺到锁资源之后会变为可运行状态, 这个过程中涉及到操作系统用户模式内核模式的转换,代价比较高。 1. CPU开销大。 在并发量很大,多个线程一直尝试更新某一个变量时,却又屡次更新不成功,这种情况下会造成CPU巨大的耗损。
2. 不能保证代码块的原子性。 只能保证某一个变量的原子性,如果想要保证多个变量的原子性就不好使了,需要动用同步锁。
3. ABA问题。 值从A->B->A
改进 真正要做到严谨的CAS机制,我们在Compare阶段不仅要比较期望值A和地址V中的实际值,还要比较变量的版本号是否一致。(核心的思想就是以前只get到当前值和内存地址中的值去比较,如果相等就就把新的修改值替换旧的期望值。只比较内存地址中的值。而现在在之前的基础上加了一个条件,比较版本号,只有内存中的值和get到的当前值相等且版本号也相等时才替换,条件变多了,更为严谨了。
  1. Java语言CAS底层如何实现? 利用unsafe提供了原子性操作方法。

  2. 什么是ABA问题?怎么解决? 当一个值从A更新成B,又更新回A,普通CAS机制会误判通过检测。 利用版本号比较可以有效解决ABA问题。


原文链接