java 多线程——CAS
公平锁 vs 非公平锁
假设三个线程 A, B, C. A 先尝试获取锁, 获取成功. 然后 B 再尝试获取锁, 获取失败, 阻塞等待; 然后 C 也尝试获取锁, C 也获取失败, 也阻塞等待.
当线程 A 释放锁的时候, 会发生啥呢?
公平锁: 遵守 “先来后到”. B 比 C 先来的. 当 A 释放锁的之后, B 就能先于 C 获取到锁.非公平锁: 不遵守 “先来后到”. B 和 C 都有可能获取到锁.
操作系统内部的线程调度就可以视为是随机
的. 如果不做任何额外
的限制, 锁就是非公平锁. 如果要想实现公平锁, 就需要依赖额外的数据结构, 来记录线程们的先后顺序.
公平锁和非公平锁没有好坏之分, 关键还是看适用场景.synchronized 是非公平锁.
可重入锁 vs 不可重入锁
可重入锁的字面意思是“可以重新进入的锁”,即允许同一个线程多次获取同一把锁。
什么是 CAS
CAS: 全称 Compare and swap,字面意思:”比较并交换“,一个 CAS 涉及到以下操作:
CAS 伪代码
当多个线程同时对某个资源进行 CAS 操作,只能有一个线程操作成功,但是并不会阻塞其他线程,其他线程只会收到操作失败的信号。
CAS 可以视为是一种乐观锁. (或者可以理解成 CAS 是乐观锁的一种实现方式)
CAS 是怎么实现的
java 的 CAS 利用的的是 unsafe 这个类提供的 CAS 操作;unsafe 的 CAS 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg;Atomic::cmpxchg 的实现使用了汇编的 CAS 操作,并使用 cpu 硬件提供的 lock 机制保证其原子性。
简而言之,是因为硬件予以了支持,软件层面才能做到。
实现原子类
标准库中提供了 java.util.concurrent.atomic 包, 里面的类都是基于这种方式来实现的.典型的就是 AtomicInteger 类. 其中的 getAndIncrement 相当于 i++ 操作.
伪代码实现:
版权声明: 本文为 InfoQ 作者【StackOverflow】的原创文章。
原文链接:【http://xie.infoq.cn/article/f309ba8c2c8753202dd9128b7】。文章转载请联系作者。
评论