I am learning Multithreading and Concurrency in Java on my own. Please help me understand this piece of code. I am creating a thread with a 'stop' boolean variable, the 'run' method loops continuously until the main thread sets the stop variable to true after sleeping for two seconds. However, I am observing this code runs in an infinite loop. What am I doing wrong here?
public class Driver {
public static void main(String[] args) {
ThreadWithStop threadWithStop = new ThreadWithStop();
Thread thread = new Thread(threadWithStop);
thread.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadWithStop.stopThread();
}
}
class ThreadWithStop implements Runnable {
private boolean stop;
public ThreadWithStop() {
this.stop = false;
}
public void stopThread() {
this.stop = true;
}
public boolean shouldRun() {
return !this.stop;
}
@Override
public void run() {
long count = 0L;
while (shouldRun()) {
count ;
}
System.out.println(count "Done!");
}
}
CodePudding user response:
Well, it is not guaranteed to stop, but it might. The change you made to the stop
by callingstopThread()
from the main thread is not guaranteed to be visible to the ThreadWithStop
until you synchronize with it somehow.
One way to achieve this would be to protect access to the variable with the synchronized
keyword - see e.g. the official Oracle tutorial on synchronized methods:
With the following changes, the change to stop
is guaranteed to be visible.
class ThreadWithStop implements Runnable {
private boolean stop;
public ThreadWithStop() {
this.stop = false;
}
public synchronized void stopThread() {
this.stop = true;
}
public synchronized boolean shouldRun() {
return !this.stop;
}
@Override
public void run() {
long count = 0L;
while (shouldRun()) {
count ;
}
System.out.println(count "Done!");
}
}
CodePudding user response:
Because they share the same variable, and the 'main' thread have the copy of the variable 'stop', the 'thread' thread also have the copy of that. If you change the 'stop', it will not be noticed immediately by 'thread' thread. We can use the keyword 'volatile', so if you change the 'stop', it will be noticed immediately.
private volatile boolean stop;