本文翻译和原创各占一半,因此仍是厚颜无耻归类到原创好了...
https://howtodoinjava.com/jav...
java 5 其中一个使人振奋的改进是新增了支持原子操做的类型,例如 AtomicInteger
, AtomicLong
等。在多线程环境中进行简单的自增自减操做时,这些原子类能帮助你减小不少用于多线程同步的复杂代码。这些原子类依赖于 CAS (compare and swap) 算法,接下来咱们会讨论 CAS 这个概念。java
传统的锁机制,例如 java 的 synchronized
关键字,他表明了 java 中悲观锁技术,保证了某一时刻仅有一个线程能访问同步代码/方法。synchronized
可以很好地工做,却有着 (相对) 比较大的性能开销。
乐观锁 (相对悲观锁) 对性能会有很大的帮助。他的核心思想是:你寄但愿于在没有冲突的状况下完成一次更新操做,使用乐观锁技术更新时会进行 “冲突检测” 来判断是否有其余的线程干扰,如果 (有其余线程干扰) 则视本次更新操做失败,通常会进行重试 (能够了解一下CAS自旋)。Compare and Swap
就是典型的乐观锁技术。算法
CAS 算法会先对一个内存变量(位置) V 和一个给定的值进行比较 A ,若是相等,则用一个新值 B 去修改这个内存变量(位置)。上述过程会做为一个原子操做完成 (intel处理器经过 cmpxchg
指令系列实现)。CAS 原子性保证了新值的计算是基于上一个有效值,期间若是内存变量(位置) V 被其余线程更新了,本线程的 CAS 更新操做将会失败。CAS 操做必须告诉调用者成功与否,能够返回一个 boolean 值来表示,或者返回一个从内存变量读到的值 (应该是上一次有效值)多线程
CAS 操做数有三个:性能
CAS 表示:“我认为如今 V 的值仍是以前我读到的旧值 A,如果则用新值 B 覆盖内存变量 V,不然不作任何动做并告诉调用者操做失败”。CAS 是一项乐观锁技术,他在更新的时候老是但愿能成功 (没有冲突),但也能检测出来自其余线程的冲突和干扰
这里咱们关注一下ReentrantLock
锁定和解锁那部分的源码ui
//ReentrantLock.lock() public void lock() { sync.lock(); }
他依赖了其内部类Sync
的 lock()
,如下是内部类 Sync
(继承了队列同步器 AQS)线程
abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; abstract void lock(); ................
Sync
仍是个抽象类,通常 new ReentrantLock()
时建立的是 NonfairSync
翻译
// ReentrantLock的构造方法 public ReentrantLock() { sync = new NonfairSync(); }
下面就是NonfairSync
的 lock()
方法了code
final void lock() { if (compareAndSetState(0, 1)) // 1 setExclusiveOwnerThread(Thread.currentThread()); // 2 else acquire(1); // 3 }
compareAndSetState()
承继自队列同步器 AQS,封装了 CAS 指令。由于是 NonfairSync
非公平锁,因此一上来就尝试抢占锁:给定旧值 0 并但愿用新值 1 去更新内存变量 State。若更新成功则视为获取锁成功,并执行 2锁用完了要释放,下面贴出 unlock()
方法继承
// ReentrantLock.unlock() public void unlock() { sync.release(1); }
这里仍是依赖了 sync,release()
是 AQS 的通用方法,其内部调用了 tryRelease()
(由 Sync 类实现),这里直接贴出 Sync 的 tryRelease()
队列
protected final boolean tryRelease(int releases) { // releases 参数的值是上面传进来的 1 int c = getState() - releases; // 1 if (Thread.currentThread() != getExclusiveOwnerThread()) // 1.5 throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { // 2 free = true; setExclusiveOwnerThread(null); } setState(c); // 3 return free; }
ReentrantLock
是可重入锁 (当前线程可屡次获取锁),因此 State 的值是能够大于 1 的。AQS 队列同步器以及 java.util.concurrent
下各类锁和原子类都运用到的 CAS 算法,有时间的同窗建议阅读加深印象。