我在LeetCode上提问时遇到了这个问题:https://leetcode.com/problems/print-in-order/
考虑两个提交内容:
1。
class Foo {
private static int signal = 0;
public Foo() {}
public synchronized void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
signal += 1;
notifyAll();
}
public synchronized void second(Runnable printSecond) throws InterruptedException {
while(signal != 1)
wait();
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
signal += 1;
notifyAll();
}
public synchronized void third(Runnable printThird) throws InterruptedException {
while(signal != 2)
wait();
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
notifyAll();
}
}
2。
class Foo {
private static int signal = 0;
public Foo() {signal = 0;}
public synchronized void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
signal += 1;
notifyAll();
}
public synchronized void second(Runnable printSecond) throws InterruptedException {
while(signal != 1)
wait();
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
signal += 1;
notifyAll();
}
public synchronized void third(Runnable printThird) throws InterruptedException {
while(signal != 2)
wait();
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
notifyAll();
}
}
尝试提交这两个,您会发现提交1将导致超过时间限制,而提交2将被接受。
唯一的区别是,在提交2中,我显式添加了一条语句signal = 0;
以初始化静态变量。因为我已经在private static int signal = 0;
中为该变量提供了默认值,所以它应该没有区别,所以这里发生了什么。我不知道Java的静态字段初始化中有什么微妙之处吗?
非常感谢您。
答案 0 :(得分:2)
LeetCode针对您的解决方案运行几个不同的测试用例。假设LeetCode在运行一个JVM并在该JVM中运行所有测试用例,但它为每种情况实例化了一个新的Foo
。
在运行第一种情况时,signal
为零,并且您的代码按预期工作。但是在此测试用例signal
的末尾现在是2,因为测试用例将其递增两次。由于它是静态的,因此它在Foo
的所有实例之间共享。即使LeetCode为第二个测试用例实例化了一个新的Foo
,静态的signal
仍为2。first
方法将其递增为3,但是由于条件{{ 1}}永远是正确的。
在while (signal != 1)
构造函数中将signal
初始化为0具有在第二次和后续测试运行之前重置Foo
的效果。
这里没有理由将signal
设为静态。它应该是常规的非静态成员,以使signal
的每个实例都获得一个初始化为零的新Foo
。