Condition接口也提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式
condition对象是依赖于lock对象的,意思就是说condition对象需要通过lock对象进行创建出来(调用Lock对象的newCondition()方法)
三个线程依次打印abc
1 public class Demo {
2
3 private int signal;
4 Lock lock = new ReentrantLock();
5 Condition a = lock.newCondition();
6 Condition b = lock.newCondition();
7 Condition c = lock.newCondition();
8
9 public void a() {
10 lock.lock();
11 while (signal != 0){
12 try {
13 a.await();
14 } catch (InterruptedException e) {
15 e.printStackTrace();
16 }
17 }
18
19 System.out.println("a");
20 signal ++;
21 b.signal();
22 lock.unlock();
23 }
24
25 public void b() {
26 lock.lock();
27 while (signal != 1){
28 try {
29 b.await();
30 } catch (InterruptedException e) {
31 e.printStackTrace();
32 }
33 }
34 System.out.println("b");
35 signal++;
36 c.signal();
37 lock.unlock();
38
39 }
40
41 public void c() {
42 lock.lock();
43 while (signal !=2){
44 try {
45 c.await();
46 } catch (InterruptedException e) {
47 e.printStackTrace();
48 }
49 }
50 System.out.println("c");
51 signal=0;
52 a.signal();
53 lock.unlock();
54 }
55
56 public static void main(String[] args) {
57
58 Demo d = new Demo();
59 A a = new A(d);
60 B b = new B(d);
61 C c = new C(d);
62
63 new Thread(a).start();
64 new Thread(b).start();
65 new Thread(c).start();
66
67
68
69 }
70
71
72 }
73
74 class A implements Runnable {
75
76 private Demo demo;
77
78 public A(Demo demo) {
79 this.demo = demo;
80 }
81
82 @Override
83 public void run() {
84 while (true) {
85 demo.a();
86 try {
87 Thread.sleep(1000);
88 } catch (InterruptedException e) {
89 e.printStackTrace();
90 }
91 }
92 }
93 }
94
95 class B implements Runnable {
96
97 private Demo demo;
98
99 public B(Demo demo) {
100 this.demo = demo;
101 }
102
103 @Override
104 public void run() {
105 while (true) {
106 demo.b();
107 try {
108 Thread.sleep(1000);
109 } catch (InterruptedException e) {
110 e.printStackTrace();
111 }
112 }
113 }
114 }
115
116 class C implements Runnable {
117
118 private Demo demo;
119
120 public C(Demo demo) {
121 this.demo = demo;
122 }
123
124 @Override
125 public void run() {
126 while (true) {
127 demo.c();
128 try {
129 Thread.sleep(1000);
130 } catch (InterruptedException e) {
131 e.printStackTrace();
132 }
133 }
134 }
135 }
Condition构造有界缓存队列
1 public class MyQueue<E> {
2
3 private Object [] obj ;
4
5 private int addIndex;
6 private int removeIndex;
7 private int queueSize;
8
9 private Lock lock = new ReentrantLock();
10
11 Condition addCondition = lock.newCondition();
12 Condition removeCondition = lock.newCondition();
13
14
15
16 public void add(E e){
17 lock.lock();
18 while (queueSize == obj.length){
19 try {
20 addCondition.await();
21 } catch (InterruptedException e1) {
22 e1.printStackTrace();
23 }
24 }
25
26 obj[addIndex++] = e;
27 if (++ addIndex == obj.length){
28 addIndex = 0;
29 }
30
31 queueSize++;
32 removeCondition.signal();
33 lock.unlock();
34
35 }
36
37 public void remove(){
38 lock.lock();
39 while (queueSize == 0){
40 try {
41 removeCondition.await();
42 } catch (InterruptedException e) {
43 e.printStackTrace();
44 }
45 }
46
47 obj[removeIndex] = null;
48 if (++removeIndex == obj.length){
49 removeIndex = 0;
50
51 }
52
53 queueSize --;
54 addCondition.signal();
55 lock.unlock();
56 }
57
58 }
Condition源码解读
在使用Condition时都是使用锁的new Condition接口实现的
lock.newCondition()
1 public Condition newCondition() {
2 return sync.newCondition();
3 }
找到同步器Sync
1 final ConditionObject newCondition() {
2 return new ConditionObject();
3 }
public class ConditionObject implements Condition, java.io.SerializableASQ的内部类,实现了Condition接口
public ConditionObject() { } 空的构造方法Condition 常用方法,,signal(),await()await() :造成当前线程在接到信号或被中断之前一直处于等待状态。signal() :唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
1 public final void await() throws InterruptedException {
2 if (Thread.interrupted())
3 throw new InterruptedException();
4 Node node = addConditionWaiter();
5 int savedState = fullyRelease(node);
6 int interruptMode = 0;
7 while (!isOnSyncQueue(node)) {
8 LockSupport.park(this);
9 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
10 break;
11 }
12 if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
13 interruptMode = REINTERRUPT;
14 if (node.nextWaiter != null) // clean up if cancelled
15 unlinkCancelledWaiters();
16 if (interruptMode != 0)
17 reportInterruptAfterWait(interruptMode);
18 }
线程中断,扔出异常
addConditionWaiter() 加入等待队列,
1 private Node addConditionWaiter() {
2 Node t = lastWaiter;
3 // If lastWaiter is cancelled, clean out.
4 if (t != null && t.waitStatus != Node.CONDITION) {
5 unlinkCancelledWaiters();
6 t = lastWaiter;
7 }
8 Node node = new Node(Thread.currentThread(), Node.CONDITION);
9 if (t == null)
10 firstWaiter = node;
11 else
12 t.nextWaiter = node;
13 lastWaiter = node;
14 return node;
15 }
头指针 firstWaiter 尾指针 lastWaiter
unlinkCancelledWaiters() 进行过滤,删除有些节点
t 指向最后一个节点
t为空,firstWaiter = node;
t不为空, t.nextWaiter = node;
t的下一个节点指向新增节点
lastWaiter = node; 下一个节点指向新增节点,
return node; 添加成功,返回,
int savedState = fullyRelease(node);
1 final int fullyRelease(Node node) {
2 boolean failed = true;
3 try {
4 int savedState = getState();
5 if (release(savedState)) {
6 failed = false;
7 return savedState;
8 } else {
9 throw new IllegalMonitorStateException();
10 }
11 } finally {
12 if (failed)
13 node.waitStatus = Node.CANCELLED;
14 }
15 }
getState()拿到状态,
释放 fullyRelease(node)
isOnlySyncQueue(node) 判断是否在同步队列中,不在同步队列中等待
唤醒后把节点放入同步队列中,进入同步队列后
12 if (acquireQueued(node, savedState) && interruptMode != THROW_IE) 13 interruptMode = REINTERRUPT; 14 if (node.nextWaiter != null) // clean up if cancelled 15 unlinkCancelledWaiters(); 16 if (interruptMode != 0) 17 reportInterruptAfterWait(interruptMode);
signal()
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
判断是否是独占节点,不是 ,抛出异常
如果第一个节点不为空,释放
1 private void doSignal(Node first) {
2 do {
3 if ( (firstWaiter = first.nextWaiter) == null)
4 lastWaiter = null;
5 first.nextWaiter = null;
6 } while (!transferForSignal(first) &&
7 (first = firstWaiter) != null);
8 }
first.nextWaiter = null,首节点的下一个节点为空,去掉首节点
transferForSignal(first)
1 final boolean transferForSignal(Node node) {
2 /*
3 * If cannot change waitStatus, the node has been cancelled.
4 */
5 if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
6 return false;
7
8 /*
9 * Splice onto queue and try to set waitStatus of predecessor to
10 * indicate that thread is (probably) waiting. If cancelled or
11 * attempt to set waitStatus fails, wake up to resync (in which
12 * case the waitStatus can be transiently and harmlessly wrong).
13 */
14 Node p = enq(node);
15 int ws = p.waitStatus;
16 if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
17 LockSupport.unpark(node.thread);
18 return true;
19 }
while (!transferForSignal(first) && (first = firstWaiter) != null)如果成功,返回false,第一个节点唤醒,do while 方法结束
同步节点失败,返回truefirstWaiter指向下一个,保证一直有叫醒的节点放到同步队列中。
Condition 其实用到AQS中的Node,通过node构建一个单向链表,await()方法向队列尾部插入一个节点
signal 就从头部移除一个节点,移除的节点放到同步队列中,
调用await方法后,将当前线程加入Condition等待队列中。当前线程释放锁。否则别的线程就无法拿到锁而发生死锁。自旋(while)挂起,不断检测节点是否在同步队列中了,如果是则尝试获取锁,否则挂起。当线程被signal方法唤醒,被唤醒的线程将从await()方法中的while循环中退出来,然后调用acquireQueued()方法竞争同步状态。
wait 和 notify 只能有一个等待队列。
Condition 能够实现多个等待队列。
完
来源:https://www.cnblogs.com/quyangyang/p/11187876.html