题目

两个线程轮流打印 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 也解锁