Why could this code fail?

While reviewing this question I noticed this code:

class MyThread extends Thread {
  private boolean stop = false;

  public void run() {
    while(!stop) {
      doSomeWork();
    }
  }

  public void setStop() {
    this.stop = true;
  }
}

However I don't understand why would this fail. Do other threads not get access to the "actual" stop variable?

Answers


The instance variable stop needs to be volatile, otherwise there's no guarantee the other threads will see changes to it. There are a lot of conflicting interests at work: threads want a consistent view of the program state, CPUs want to be able to cache data, the JVM wants to be able to reorder instructions. Making the instance variable volatile means that it can't be cached and that happens-before relationships are established that limit instruction reordering.

See this other answer (+1) for a good example of what reordering may happen without marking the variable volatile.

(By the way using interruption for thread cancellation is preferable to using an instance variable.)


The JIT compiler can re-order reads and writes in an application so long as

  1. the actions are sequentially consistent and
  2. the altered actions do not violate intra-thread semantics.

That is just a fancy way of saying, all actions should appear to happen the same way as if it were executed by only a single thread. So you can get the JIT to recompile your code to look like this

class MyThread extends Thread {
  private boolean stop = false;

  public void run() {
    if(!stop){
       while(true){

       }
    }
  }

This is a legal optimization called hoisting. It still acts the same as if serial but offers surprising results when using multiple threads.

By declaring a field volatile you are telling Java not to execute any re orderings. Along with the memory consistency as mentioned by Nathan Hughes


Need Your Help

processing large cloud storage files in app engine

python google-app-engine google-cloud-storage

I'm required to process large files, up to 2GB, in GAE (I'm using Python).

Ruby on Rails Twitter trends - TypeError = can't convert string into integer?

ruby-on-rails ruby twitter

I'm getting a really strange error message in my app. In my controller I have:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.