Inspired by the following leet-code
Suppose you are given the following code:
class FooBar { public void foo() { for (int i = 0; i < n; i++) { print("foo"); } } public void bar() { for (int i = 0; i < n; i++) { print("bar"); } } }
The same instance of
FooBar
will be passed to two different threads. Thread A will callfoo()
while thread B will callbar()
. Modify the given program to output"foobar"
n times.Example 1:
Input: n = 1 Output: "foobar" Explanation: There are two threads being fired asynchronously. One of them calls foo(), while the other calls bar(). "foobar" is being output 1 time.
Example 2:
Input: n = 2 Output: "foobarfoobar" Explanation: "foobar" is being output 2 times.
My solution, which is was accepted:
class FooBar {
private static class Syncer {
int status;
}
private int n;
private Syncer syncer = new Syncer();
public FooBar(int n) {
this.n = n;
}
public void foo(Runnable printFoo) throws InterruptedException {
synchronized(syncer) {
for (int i = 0; i < n; i++) {
while (syncer.status != 0){
syncer.wait();
}
printFoo.run();
syncer.status = 1;
syncer.notifyAll();
}
}
}
public void bar(Runnable printBar) throws InterruptedException {
synchronized(syncer) {
for (int i = 0; i < n; i++) {
while (syncer.status != 1){
syncer.wait();
}
printBar.run();
syncer.status = 0;
syncer.notifyAll();
}
}
}
}
Questions:
- Do you see any cases, where this solution would not work? (Assuming the input is correct, i.e.
n>=1
.)
I'm thinking of cases where one thread would not necessarily see the changes to syncer
due to it not being volatile and synchronized. (I know this exact issue does not affect my solution, because syncer
is, in fact synchronized, so what I mean if there are other similar "pitfalls" which affect the code above.)
Do you see any issues with performance? (I know the code waits in a while-loop, but it calls
wait
, which is supposed to be optimal.)In general, is there a way this solution could be improved?
Does this pattern (threads running multiple times in a given order and waiting for each other) have a name, or a high-level Java concurrency object which implements them? (Slightly related: what better name would you give to
syncer
?)