接 上一章
依然这个网址: 找到一个不错的博客,很全:
http://www.cnblogs.com/skywang12345/p/3496098.html
Object Condition 休眠 wait await 唤醒个线程 notify signal 唤醒所有线程 notifyAll signalAll
Condition除了可以用await+signal替代 wait+notify 之外,它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。
公平锁和非公平锁的测试 见网址:
https://blog.csdn.net/jiang13479/article/details/80679794
ReentrantLock构造函数默认为 非公平锁,非公平锁性能好,因为不需要维护一个链表队列。
构造函数 传true为 公平锁:new ReentrantLock(true);
Condition 的 await 和 signal 也维护了 一个链表, 使用await 时 ,将当前Condition 对应的链表的末尾加上 当前await线程:
使用signal时 ,获取当前Condition 对应的链表的第一个node节点;并且将第二个node节点 置为第一个。
//使用signal时 ,获取当前Condition 对应的链表的第一个node节点
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
//第一个node节点对应的线程已经被唤醒;将第二个node节点 置为第一个
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
//将当前Condition 对应的链表的末尾加上 当前await线程
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。
LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
因为park() 和 unpark()有许可的存在;调用 park() 的线程和另一个试图将其 unpark() 的线程之间的竞争将保持活性。
下一章 进入共享锁。