0

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!");
    }
}
5
  • This code works fine. Its not looping for ever for me! Commented Oct 20, 2021 at 14:23
  • 1
    @Kris , sadly, just because it runs fine on your setup does not mean the code is fine. This is why concurrency is a hard topic. Here there clearly is a visibility issue on the modification of the boolean flag. It's surprising that such a simple example should highlight the issue, but is is very clear from the specification of the language that, in the absence of any kind of synchronisation, the mutation of the boolean might not be visible by any other thread than the one performing the change. Commented Oct 20, 2021 at 14:31
  • @GPI I agree, but do you see any other thread in this context making changes ? Commented Oct 20, 2021 at 14:32
  • 1
    As I read the question, the "main" thread does the mutation, the secondary thead "ThreadWithStop" is "watching" the modified boolean, from another thread. Commented Oct 20, 2021 at 14:33
  • Shouldn't volatile the variable stop solve the problem? Commented Oct 20, 2021 at 14:54

1 Answer 1

2

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 synchronizedkeyword - 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!");
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.