Reputation: 13
I encountered this problem when doing a question on LeetCode: https://leetcode.com/problems/print-in-order/
Consider two submissions:
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();
}
}
Try submitting these two and you'll find submission 1 will result in Time Limit Exceeded while submission 2 will be accepted.
The only difference is that in submission 2, I explicitly added a statement signal = 0;
to initialize the static variable. It should play no difference as I have already given this variable a default value in private static int signal = 0;
, so what is going on here. Is there any subtleties in the static field initialization in Java that I did not know?
Thank you very much.
Upvotes: 1
Views: 80
Reputation: 8204
LeetCode runs several different test cases against your solution. Let's assume that LeetCode is running a single JVM and running all the test cases in that JVM, but it is instantiating a new Foo
for each case.
When running the first case, signal
is zero, and your code works as expected. But at the end of this test case signal
is now 2, because the test case increments it twice. Since it is static, it is shared among all instances of Foo
. Even though LeetCode instantiates a new Foo
for the second test case, the static signal
is still 2. The first
method increments it to 3, but then the test hangs because the condition while (signal != 1)
is always true.
Initializing signal
to 0 in the Foo
constructor has the effect of resetting signal
before the second and subsequent test runs.
There's no reason to make signal
static here. It should be a regular non-static member so that each instance of Foo
gets a new signal
initialized to zero.
Upvotes: 2