并发题 - 两个线程轮流打印 1 - 100
题目
两个线程轮流打印 1 - 100,必须使用 ReentrantLock 实现
思路
使用 condition 和 reentrantlock 即可配合实现有序,一个线程中调用 condition.await,该线程就会加入该 condition 对应的等待队列,再从另一个线程唤醒 condition 的线程,就可以让线程相互协作
class T1 extends Thread { Lock lock; Condition c1; Condition c2; private AtomicInteger count; public T1(Lock lock, Condition c1, Condition c2, AtomicInteger count) { this.lock = lock; this.c1 = c1; this.c2 = c2; this.count = count; } public void run() { lock.lock(); try { T2.working(count, c2, c1); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } class T2 extends Thread { private Lock lock; private Condition c1; private Condition c2; private AtomicInteger count; public T2(Lock lock, Condition c1, Condition c2, AtomicInteger count) { this.lock = lock; this.c1 = c1; this.c2 = c2; this.count = count; } public void run() { lock.lock(); try { working(count, c1, c2); } catch (InterruptedException e) { e.printStackTrace(); } finally { if (count.get() == 101) { c1.signal(); //保证先把自己锁的线程一定能结束 } lock.unlock(); } } public static void working(AtomicInteger count, Condition c1, Condition c2) throws InterruptedException { while (count.get() <= 100) { System.out.println(count); count.incrementAndGet(); c1.signal(); c2.await(); } } } class Main { public static void main(String[] args) { Lock lock = new ReentrantLock(); Condition c1 = lock.newCondition(); Condition c2 = lock.newCondition(); AtomicInteger count = new AtomicInteger(0); T1 t1 = new T1(lock, c1, c2, count); T2 t2 = new T2(lock, c1, c2, count); t1.start(); t2.start(); } }
总结
如果 T2 的 finally 没有对 if 的判断,会发现线程会卡住,思考一下原因:
- 100 的时候,T1 signal T2,T1 await 本身
- 101 的时候,T2 无法进入 while,那么 T2 解锁后结束,此时发现 T1 还卡住呢
所以,得加上判断最后让 T1 也解锁