There are a few issues that I can see in your code.
First, both of the loops are are not updating variable j
.
Next, the use of wait/wait()
. The java docs for the wait
method
(https://www.oracle.com/java/jaDocs/jaapi/java/lang/Object.html#wait ) specifically note that "interruptions and spurious
wakeups are possible, and this method should ALWAYS be used in a loop" The wait
method is designed for use with condition variables
(https://cseweb.ucsd.edu/classes/sp17/cse120-a/lectures/ln/lecture7.html ), so there needs to be both a condition and a loop.
Next note that there is a logic error. If the goal is to have the writing and reading be ordered so that before
and after
are never equal, there needs to be a wait
call before the call to add
, and a wait
call after doing the before read.
Normally, the Thread
class implements wait()
and wait(long)
, but in our case, we have a synchronized
block that calls wait()
on the Object
passed to it.
The following is a version of your code with my changes, I have added comments to the code to explain the changes I have made.
<!-- the following code uses a `synchronized` block on an `Object` -->
public class Main3 {
private static volatile int i = 0;
private static volatile boolean write = false;
private static volatile boolean read = false;
private final static Object o = new Object();
private static void add()
{
i++;
}
public static void main(String[] args) throws InterruptedException {
//The first thread performs the write operation
Thread th1 = new <!-- it is always good practice to name your thread --> MyThread1() {
public void run() {
for (int j = 0; j < 10000; j++) {
synchronized (o) {
// The following line added a `while` loop to check the value of `write`
while (!write) {
try {
o.wait();
} catch (InterruptedException e) {
throw new IllegalThreadException(e);
}
}
add();
// the following two lines were inverted
write = false;
read = true;
o.wait();
}
}
}
};
//The second thread performs the read operation
Thread th2 = new <!-- it is always good practice to name your thread --> MyThread2() {
public void run() {
for (int j = 0; j < 10000; j++) {
int before;
int after;
synchronized (o) {
// the following two lines were inverted
read = true;
o.wait();
before = i;
// the following line was added to the top of the `else` block
if (!write) {
write = true;
o.wait();
} else {
o.wait();
}
after = i;
}
// the following conditional statement was added.
if( before == after )
{
System.out.println( "before: " + before + " after: " + after );
}
}
}
};
th1.start();
th2.start();
th1.join();
th2.join();
System.out.println(i);
}
}
```