ReentrantLockのConditionによるスレッド間の通信


Conditionはスレッド間の通信を実現し,awatとsignalの2つの方法によってスレッド間の通信連携を実現することができる.
ここではConditionを利用して、3つのスレッドを開いて、スレッドを順番にA、B、Cを循環印刷させる機能を実現します.
プライマリ・コードは次のとおりです.
static final ReentrantLock lock = new ReentrantLock();
    static AtomicBoolean firstA = new AtomicBoolean(true);
    static class PrintRunable implements Runnable{

        private String str;
        private Condition await;
        private Condition signal;

        public PrintRunable(String str, Condition await, Condition signal) {
            this.str = str;
            this.await = await;
            this.signal = signal;
        }

        @Override
        public void run() {
            //      A ,         
            if (firstA.get() && "A".equals(str)) {
                lock.lock();
                try {
                    System.out.println(str);
                    firstA.getAndSet(true);
                    TimeUnit.SECONDS.sleep(1);
                    signal.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
            while (true) {
                while (true) {
                    lock.lock();
                    try {
                        //     
                        await.await();
                        System.out.println(str);
                        TimeUnit.SECONDS.sleep(1);
                        //           
                        signal.signal();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
    }
テスト:
@Test
    public void reentrantLockTest() throws Exception {
        final Condition condition1 = lock.newCondition();
        final Condition condition2 = lock.newCondition();
        final Condition condition3 = lock.newCondition();

        Thread a = new Thread(new PrintRunable("A",condition1,condition2));
        Thread b = new Thread(new PrintRunable("B",condition2,condition3));
        Thread c = new Thread(new PrintRunable("C",condition3,condition1));

        b.start();
        c.start();
        a.start();
        b.join();
        a.join();
        c.join();

    }

コンソール印刷:
A
B
C
A
B
C
A
B
C

まとめ:
ReentrantLockは独占ロックで、1つのスレッドがロックを手に入れた後に解放しなければ、もう1つのスレッドはロックを手に入れられないに違いないのでlock.lock()とlock.unlock()の間には、ロックを解除する操作が1回ある可能性があります(同様に、ロックを取得する操作も必ず1回あります).take()もput()もlockに入っています.ロック()後にロックを解除できる唯一の操作はawait()です.すなわちawait()操作は実際にはロックを解放し、スレッドを掛け、条件が満たされると起動し、再びロックを取得することである.これはwaitとnotifyに似ています.waitもロックを解放します.sleepはロックを解放しません.