문제

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?

도움이 되었습니까?

해결책 2

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

The variable stop must be declared as volatile.

Although i prefer using interrupt to stop a thread.

Other threads are not guaranteed to see updated values of stop - you need to establish a "happens before" relationship. The simplest way would be to make stop volatile.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top