Condition是一个接口,AQS中的ConditionObject内部类实现了此接口。
使用方式:生产者,消费者模型
public class Producer implements Runnable{
private Queue<String> msg;
private int maxSize;
private Lock lock;
private Condition condition;
public Producer(Queue<String> msg, int maxSize, Lock lock, Condition condition) {
this.msg = msg;
this.maxSize = maxSize;
this.lock = lock;
this.condition = condition;
}
@Override
public void run() {
int i = 0;
while (true){
i++;
lock.lock();
while (msg.size() == maxSize){
System.out.println("生产者队列满了,先等待");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产者生产消息:" + i);
msg.add("生产者的消息内容:" + i);
condition.signal();
lock.unlock();
}
}
}
public class Consumer implements Runnable {
private Queue<String> msg;
private int maxSize;
private Lock lock;
private Condition condition;
public Consumer(Queue<String> msg, int maxSize, Lock lock, Condition condition) {
this.msg = msg;
this.maxSize = maxSize;
this.lock = lock;
this.condition = condition;
}
@Override
public void run() {
int i = 0;
while (true){
i++;
lock.lock();
while (msg.isEmpty()){
System.out.println("消费者队列空了,先等待");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者消费消息:"+ i + "," + msg.remove());
condition.signal();
lock.unlock();
}
}
}
public class TestCondition {
public static void main(String[] args) {
Queue queue = new LinkedList();
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
int maxSize = 5;
Producer producer = new Producer(queue,maxSize,lock,condition);
Consumer consumer = new Consumer(queue,maxSize,lock,condition);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
}
源码阅读
// 使获得锁的当前线程放弃资源,阻塞(直到被唤醒或interrupted)
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//把当前获得锁的线程加入到Condition阻塞队列中(单线链表)
Node node = addConditionWaiter();
// 释放锁,完整的释放,把重入的都释放掉。即state=0,并唤醒同步队列中阻塞的线程
int savedState = fullyRelease(node);
int interruptMode = 0;
// 判断当前节点是否在同步队列中(当前节点是在Condition队列中),不在的话就阻塞
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阻塞队列中(单线链表)
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
// 构建一个Node,Node.CONDITION表示条件队列
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
// 清除失效节点
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
// 释放锁,完整的释放,把重入的都释放掉。即state=0,并唤醒同步队列中阻塞的线程
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) {
// tryRelease(arg)重入状态的话state-1,减到0就变成无锁,无锁返回true
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
// unpark唤醒
unparkSuccessor(h);
return true;
}
return false;
}
// 重入状态的话State-1,减到0就变成无锁
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;
}
// 判断当前节点是否在同步队列中
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
return findNodeFromTail(node);
}
// 唤醒await阻塞的线程,就是唤醒Condition队列中的线程.
// 把Condition队列中的线程唤醒后,把它加入到同步队列中等待unlock
// 如果前一个节点已经失效,则直接唤醒
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
// 检查node的状态是否被更改了,没被更改返回true,更改了就返回fasle,返回true结束循环
} while (!transferForSignal(first) &&
// 返回true则去除被更改的节点,重新循环直到找到正常的节点
(first = firstWaiter) != null);
}
// 检查node的状态是否被更改了,没被更改返回true,更改了就返回fasle
final boolean transferForSignal(Node node) {
// 检测node的状态是否更改了,如果更改了就返回false
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 把node节点加入到同步队列中,并返回上一个节点,即tail
Node p = enq(node);
int ws = p.waitStatus;
// 提升性能的写法,如果p节点已经失效则直接唤醒node节点。
// 因为只有在unlock方法后才会唤醒同步阻塞队列中的线程,唤醒前需要把失效的节点移出去,
// 需要循环节点,p节点已经失效,就浪费了一次判断的过程,
// 这里直接唤醒还可以更快的把await后面没有执行完的代码执行完
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
private Node enq(final Node node) {
//自旋
for (;;) {
Node t = tail;
// 尾节点=null
if (t == null) { // Must initialize
// 初始化头部Node
if (compareAndSetHead(new Node()))
// 头节点,尾节点指向同一个节点Node
tail = head;
} else {
// 当前节点的上一个节点指向尾节点
node.prev = t;
// 更改尾部节点为当前节点
if (compareAndSetTail(t, node)) {
// 之前尾节点的下一个节点指向当前节点
t.next = node;
return t;
}
}
}
}
// 判断当前节点是否在同步队列中(当前节点是在Condition队列中),不在的话就阻塞
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);
}
// 去抢占锁或者阻塞,node为没有获取到锁的线程的node
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 自旋
for (;;) {
// p为当前node的上一个node
final Node p = node.predecessor();
// 如果是head节点的话,会去抢占一次锁
if (p == head && tryAcquire(arg)) {
// 当前节点设置为头结点
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// shouldParkAfterFailedAcquire(Node pred, Node node)抢占锁失败后是否要挂起,true挂起,false不挂起
// parkAndCheckInterrupt()用来挂起
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
// interrupted = true向上传递,让后续的代码知道线程中断过
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}