java,什么时候(以及多长时间)线程可以缓存非易失性变量的值?

Dav*_*lla 7 java concurrency

从这篇文章:http://www.javamex.com/tutorials/synchronization_volatile_typical_use.shtml

public class StoppableTask extends Thread {
  private volatile boolean pleaseStop;

  public void run() {
    while (!pleaseStop) {
      // do some stuff...
    }
  }

  public void tellMeToStop() {
    pleaseStop = true;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果变量未被声明为volatile(并且没有其他同步),则运行循环的线程在循环开始时缓存变量的值并且永远不会再次读取它是合法的.

在Java 5或更高版本中:

最后一段是否正确?

那么,在什么时候线程可以缓存pleaseStop变量的值(以及多长时间)?就在调用StoppableTask的一个函数(run,tellMeTpStop)之前?(并且线程必须在最迟退出函数时更新变量?)

你能指点我的文档/教程参考(Java 5或更高版本)吗?


更新:这是我在这个问题上发布的答案汇编:

不使用volatilenor synchronized,上述程序实际上存在两个问题:

1-线程可以pleaseStop从线程启动的第一个时刻开始缓存变量,并且不会再次更新它.所以,循环会永远持续下去.这可以通过使用volatile或解决synchronized.C 中存在此线程缓存机制.

2- java编译器可以优化代码,并替换while(!pleaseStop) {...}if (!pleaseStop) { while (true) {...}}.所以,循环会永远持续下去.再次,这可以通过使用volatile或解决synchronized.此编译器优化也存在于C.

更多信息:https: //www.ibm.com/developerworks/library/j-5things15/

aug*_*ray 5

什么时候可以缓存?

至于您有关“何时可以缓存”值的问题,答案是“始终”。要了解这意味着什么,请继续阅读。处理器具有称为高速缓存的存储,这使正在运行的线程可以通过从高速缓存而非内存中进行读取来访问内存中的值。正在运行的线程也可以写入此缓存,就像它正在将值写入内存一样。因此,只要线程正在运行,它就可以使用缓存来存储其使用的数据。必须明确地发生某种事情才能将值从缓存刷新到内存。对于单线程进程,这一切都很好,但如果您有另一个线程,它可能正试图从内存中读取数据,而另一个线程正在将读写数据写入处理器高速缓存,而不会刷新到内存。

它可以缓存多长时间?

至于“持续多长时间”部分,除非您对此不做任何选择,否则答案是永远的。对有问题的数据进行同步是一种强制从缓存中进行刷新的方法,以便所有线程都可以看到该值的更新。有关导致冲洗的方法的更多详细信息,请参阅下一节。

文件在哪里?

至于“文档在哪里”的问题,这里是一个不错的起点。对于如何强制执行刷新,java通过讨论一个动作(例如数据写入)是否似乎在另一个动作(例如数据读取)之前“发生”来引用此内容。有关更多信息,请参见此处

volatile

volatile从本质上讲,可以防止上述类型的处理器缓存。这样可以确保从其他线程可见对变量的所有写入。要了解更多信息,您所链接的教程似乎是一个好的开始。