题解 | 条件变量实现数字的交替输出
今天摸鱼逛博客园,看到一个并发题目,考察条件变量的使用:
题目:使用条件变量(
AQS.Condition
),实现两个线程交替输出从0到100,规定线程A先输出,线程B后输出,前者输出偶数,后者输出奇数
我的实现方法如下:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Solution {
private final static ReentrantLock lock = new ReentrantLock();
private static int value = 0;
public static void main(String[] args) {
Condition l0 = lock.newCondition(); // 等待偶数的条件
Condition l1 = lock.newCondition(); // 等待奇数的条件
System.out.println("Tread A first print!");
Thread threadA = new Thread(() -> {
while (true) {
if (value >= 100) {
break;
}
try {
lock.lock();
while(value % 2 != 0) { // while防止虚假唤醒
l0.await();
}
System.out.println("Thread A start to print —— " + value++);
l1.signalAll(); // 也可以signal
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
Thread threadB = new Thread(() -> {
while (true) {
if (value >= 100) {
break;
}
try {
lock.lock();
while(value % 2 == 0) {
l1.await();
}
System.out.println("Thread B start to print —— " + value++);
l0.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
threadA.start();
threadB.start();
}
}
之前虽然把AQS
、ReentrantLock
的源码都看了好几遍,但是真正自己动手写多线程代码,还是有些生疏-_-||
值得注意的有三点:
- 使用条件变量之前,必须先获取锁。如果是
ReentrantLock
创建出来的条件变量,必须将条件变量的await
和signal
方法包裹在lock
和unlock
中使用。await
方法会释放获取到的锁,当等待的条件满足时,会重新获取锁,这点不用担心 - 如果要同步两个线程,需要两个条件变量,另外还需要外界的一个条件来帮助判断,光靠两个条件变量的
await
和signal
会发生死锁。这里使用的条件是value是否为偶数。如果是生产者-消费者模型中,条件就应该是队列是否为空。这些条件都应该放在while
循环而不是if
条件中,这是为了防止虚假唤醒 - 以后要多练练使用Idea调试多线程代码,不容易但也没有想象中那么难
愿归来仍是少年!
作者:酒冽
出处:https://www.cnblogs.com/frankiedyz/p/15639964.html
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
出处:https://www.cnblogs.com/frankiedyz/p/15639964.html
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任