昨天的文章 我们针对 Java 语言的 "happends-before" 原则做了一个非常简单的表述,以致于有同学提到我这个话语的严谨性问题。而这个原则在 Java 语言里面非常重要,以致于我必须重新引用一下相关书籍的话来进行论述。
"happends-before" 先行发生原则是 Java 内存模型中定义的两项操作之间的偏序关系,如果说操作 A 先行发生于操作 B,那么操作 A 产生的影响一定应该被操作 B 所观察到。
而对于我们 volatile
保证的可见性, synchronized
和 final
关键字也同样可以做到。那我们今天就来简单讲一下我们非常常用的 synchronized
和似乎在 Android 中少有听到的 CAS 机制。
synchronized 和 CAS 的区别
synchronized
采用的是 CPU 悲观锁机制,即线程获得的是独占锁。独占锁就意味着 其他线程只能依靠阻塞来等待线程释放锁。而在 CPU 转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起 CPU 频繁的上下文切换导致效率很低。尽管 Java1.6 为 synchronized
做了优化,增加了从偏向锁到轻量级锁再到重量级锁的过度,但是在最终转变为重量级锁之后,性能仍然较低。
CAS 是英文单词 Compare And Swap 的缩写,翻译过来就是比较并替换。它当中使用了3个基本操作数:内存地址 V,旧的预期值 A,要修改的新值 B。采用的是一种乐观锁的机制,它不会阻塞任何线程,所以在效率上,它会比 synchronized
要高。所谓乐观锁就是:每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
所以,在并发量非常高的情况下,我们尽量的用同步锁,而在其他情况下,我们可以灵活的采用 CAS 机制。
那些地方采用了 CAS 机制
在 java.util.concurrent.atomic
包下,一系列以 Atomic
开头的包装类。例如AtomicBoolean
,AtomicInteger
,AtomicLong
等,它们就是典型的利用 CAS 机制实现的原子操作类。
此外,Lock
系列类的底层实现以及 Java 1.6 在 synchronized
转换为重量级锁之前,也会采用到 CAS 机制。
关于 CAS 机制的更多相关信息请移步:
漫画:什么是CAS机制?(进阶篇)
网友评论