condition
先来一个示例:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockStu {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock(false);
Condition condition = reentrantLock.newCondition();
for(int i = 0; i<5 ; i++){
new Thread(()->{
reentrantLock.lock();
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----------------------"+Thread.currentThread().getName());
reentrantLock.unlock();
},"yc"+i).start();
}
new Thread(()->{
reentrantLock.lock();
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+"------------停留了2s-----------");
} catch (InterruptedException e) {
e.printStackTrace();
}
condition.signalAll();
reentrantLock.unlock();
},"yc5").start();
}
}
yc5------------停留了2s-----------
-----------------------yc0
-----------------------yc1
-----------------------yc2
-----------------------yc3
-----------------------yc4
reentrantLock.lock();咱就不说了,看下上一篇帖子,其就是如果当前state=1的话,就cas获取锁资源,获取不到就乖乖去排队
假设 yc0获取了锁资源,yc1,yc2,yc3,yc4在AQS队列中
时间t1:y0线程已经拿到互斥锁了,其他线程都堵塞了,进入了aqs队列,
时间t2:y0执行condition.await();
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter(); //创建一个条件队列,并加入这个队列
int savedState = fullyRelease(node);//释放当前线程的互斥锁,并唤醒AQS队列中head节点下一个节点
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);
}
来看下addConditionWaiter这个方法怎么创建条件队列的:
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;
}
fullyRelease其主要是释放当前锁,然后唤醒此时head节点的下一个节点
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
这个用cas 把state - 1 ,把自己身获取排斥锁的状态至null
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
唤醒队列中的head下一个节点,去争抢资源,因此此时state == 0了
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
接下就是执行LockSupport.park(this); 把自己给堵塞了,
t10: 这个时候,所有的线程都添加到条件队列里面去了,
t12:这个时候线程5获取了锁,并且去执行了 condition.signalAll();
condition.signalAll() 大概就是把条件队列里面的节点都移到 AQS队列中去,并且都唤醒他们,去争夺资源
注意:condition.signal() 是从条件队列里面取一个出来放到AQS队列里面去的
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}
t13:这个时候线程y5已经unlock了,这个时候,被移到 AQS队列中的线程可以去争抢资源了,接下来就跟reentrantlock一样了
CyclicBarrier
这个可以认为可以多次循环使用 condition中的 await signelAll , await signelAll
其中barrier.await(); 可以多次调用
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count; //每个线程获得锁都会-1
if (index == 0) { // 最后获得到锁的线程会执行回调方法
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration(); //最后一个线程会signelAll条件队列中所有的线程
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await(); //把AQS队列中的节点移到条件队列中,并释放自己的锁,唤醒别的线程去获取到锁执行 --count
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}