leetcode 1117.H 2 O生成補完Semaphore(信号量)知識欠落


タイトルの説明
現在、2つのスレッド、酸素oxygenと水素hydrogenがあり、あなたの目標はこの2つのスレッドを組織して水分子を生成することです.
バリア(barrier)が存在し、各スレッドは、完全な水分子が生成されるまで待たなければならない.
水素および酸素スレッドは、バリアを突破するためにreleaseHydrogenおよびreleaseOxygen法にそれぞれ与えられる.
これらのスレッドは3つのグループがバリアを突破し、直ちに1つの水分子を生成することができるべきである.
水分子を生成するために必要なスレッドの結合が次の水分子を生成する前に発生しなければならないことを保証しなければなりません.
言い換えれば、
1つの酸素スレッドがバリアに到達したときに水素スレッドが到達しない場合、2つの水素スレッドが到達するまで待たなければならない.1つの水素スレッドがバリアに到達したときに他のスレッドが到達しない場合、1つの酸素スレッドと別の水素スレッドが到達するまで待たなければならない.これらの制限条件を満たす水素,酸素スレッド同期コードを書く.
例1:
入力:「HOH」出力:「HHO」解釈:「HOH」と「OHH」は依然として有効解である.例2:
入力:「OOHHHH」出力:「HHOHHO」解釈:「HOHHO」、「OHHHO」、「HHOH」、「HOHHOH」、「HOHHOH」、「OHHHOH」、「HHOHH」、「HOHOHH」、「OHHOH」、「OHHOHHOH」、「OHHOHHOH」は依然として有効解である.
ヒント:
入力文字列の総長は3 n,1≦n≦50である.入力文字列の「H」の合計数は2 nになります.入力文字列の「O」の合計数はnになります.
ソース:力ボタン(LeetCode)リンク:https://leetcode-cn.com/problems/building-h2o
私の解法
class H2O {

    Semaphore h = new Semaphore(2);
    Semaphore o = new Semaphore(0);

    public H2O() {
        
    }

    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
		h.acquire();
        // releaseHydrogen.run() outputs "H". Do not change or remove this line.
        releaseHydrogen.run();
        o.release();
    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        o.acquire(2);
        // releaseOxygen.run() outputs "O". Do not change or remove this line.
		releaseOxygen.run();
        h.release(2);
    }
}

実行時間:19 ms、すべてのJavaコミットで48.18%のユーザーメモリ消費量:41.9 MBを破り、すべてのJavaコミットで12.06%のユーザーを破った
知識が足りない.
最初はなぜo.acquire(2);が最後の行h.release(2);で2つのpermitsを解放したのか理解できなかったが、hydrogen法の最初の行h.acquire();は1つのpermitしか消費しなかったので、次に1つのreleaseHydrogen.run();を2回実行し、o.acquire(2);は2つのpermitsを直接消費することに相当し、つまり1回のreleaseOxygen.run();を実行することに相当する.