共享锁AQS中的实现
共享锁在AQS中实现非常简单.
当独占锁的Node取得锁后,便结束了, 而一旦共享锁的node取得锁,便会一直向下propagate传递, 把后面排队的线程全部唤醒, 直到当前的state变成0为止. 这和重入锁的原理有些类似.
并且, tryaquire()和tryrelease()此时会改成tryacuireShared()和tryreleaseShared(), 在之前的CAS基础上对state的状态, 从3 到 2 到1 到 0.
Condition的实现
和之前的CLH队列类似, 只是队列拥有多个condition在等待, 每一个状态拥有一个condition
await(): 把当前节点加入到condition队列的尾部, 让Node进入所谓的park状态
signal():唤醒condition下面的第一个node, 让这个node重新进行入队addWaiter();
signal() vs.signalAll()
之前在notify()和notifyAll()中, 尽量使用notifyAll()是因为可能有多个参数发生改变 (ex.车里程数或油耗改变, 通知系统)
而因为显示锁可以拥有多个condition, 比如说, mileCondition, oilCondition, 因此在condition中的signal()方法只需要signal()一个就可以.
signalAll(): signalAll()的使用在于当一个任务结束,需要唤醒一个Condition队列下的多个线程去做很多不同的时期,这时候用signalAll(), 当然signalAll()只用于一个condition队列下的所有等待的node.
重入锁的实现
在tryAcquire中,检查是否是当前线程已拿锁,然后用CAS对CompareAndSetState做出改变
公平锁的实现
在tryAcuiqre()中,公平锁会先看一看CLH队列中有没有node, 如果没有的话直接加入, 否则就尝试addWaiter()去尾部
重入锁中的读锁和写锁
如图, 分别有一个读锁和一个写锁. 在读锁中, 和写锁进行互斥。在写锁中, 和读锁还有其他写锁进行互斥, 那么是如何实现的呢?
首先, readLock()和writeLock()中共享一个int state,然后这个int的前16位是读锁,后16位是写锁.
然后给了写锁一个threadLocal()来记录可重入问题。
网友评论