这个问题来自 LeetCode。https://leetcode.com/problems/building-h2o/
对于不同的测试用例,我提出的以下代码大约有五分之一失败。其中一个测试用例是“HHOHHOOOOHHHHHH”。我没有重现这个确切测试用例的代码,因为它对用户隐藏,可以在网站上输入以下代码和测试用例进行重现。
public class H2O {
final CyclicBarrier barrier = new CyclicBarrier(3);
int h;
int o;
final Semaphore hydroWaiting = new Semaphore(0);
final Semaphore oxWaiting = new Semaphore(0);
final Lock lock = new ReentrantLock();
public H2O() {
}
public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
lock.lock();
h++;
boolean last = false;
if (h >= 2 && o >= 1) {
h -= 2;
o -= 1;
oxWaiting.release(1);
hydroWaiting.release(1);
last = true;
} else {
lock.unlock();
hydroWaiting.acquire();
}
try {
System.out.println("Hydrogen Thread " + Thread.currentThread().getName() + " awaiting barrier");
barrier.await();
releaseHydrogen.run();
System.out.println("Hydrogen Thread " + Thread.currentThread().getName() + " released");
} catch (Exception e) {
System.out.println("Barrier Broken");
} finally {
if (last) {
lock.unlock();
}
}
}
public void oxygen(Runnable releaseOxygen) throws InterruptedException {
lock.lock();
o++;
boolean last = false;
if (h >= 2 && o >= 1) {
h -= 2;
o -= 1;
hydroWaiting.release(2);
last = true;
} else {
lock.unlock();
oxWaiting.acquire();
}
System.out.println("Oxygen Thread " + Thread.currentThread().getName() + " awaiting barrier");
try {
barrier.await();
releaseOxygen.run();
System.out.println("Oxygen Thread " + Thread.currentThread().getName() + " released");
} catch (Exception e) {
System.out.println("Barrier Broken");
} finally {
if (last) {
lock.unlock();
}
}
}
}
我花了很多时间调试,也尝试在我的本地重现,但没能做到。失败的运行具有我添加的打印语句的以下输出:
Output: "OOH HHH OHH OHH OHH" (spread out for readability)
Hydrogen Thread Thread-0 awaiting barrier
Hydrogen Thread Thread-1 awaiting barrier
Oxygen Thread Thread-2 awaiting barrier
Oxygen Thread Thread-2 released
Hydrogen Thread Thread-3 awaiting barrier
Hydrogen Thread Thread-4 awaiting barrier
Oxygen Thread Thread-5 awaiting barrier
Oxygen Thread Thread-5 released
Hydrogen Thread Thread-0 released
Hydrogen Thread Thread-1 released
Hydrogen Thread Thread-3 released
Hydrogen Thread Thread-4 released
如您所见,CyclicBarrier 的行为与输出的预期不同,即没有立即释放屏障中的所有线程。但这仅发生在 Leetcode 编译器中。有人可以指出代码中是否存在错误或者是 Leetcode 的问题吗?