今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。

鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?


当前回答

使用volatile的一个常见示例是使用volatile布尔变量作为终止线程的标志。如果您已经启动了一个线程,并且希望能够安全地从另一个线程中断它,您可以让线程定期检查标志。要阻止它,将标志设置为true。通过将标志设置为易失性,可以确保正在检查它的线程在下次检查时看到它已经设置好,甚至不必使用同步块。

其他回答

Volatile具有内存可见性的语义。基本上,volatile字段的值在写操作完成后对所有读取器(特别是其他线程)可见。如果没有volatile,读者可以看到一些未更新的值。

回答您的问题:是的,我使用一个volatile变量来控制某些代码是否继续循环。循环测试易变值,如果为真则继续。可以通过调用“stop”方法将条件设置为false。循环看到false,并在stop方法完成执行后测试该值时终止。

我强烈推荐的《Java并发实践》一书对volatile做了很好的解释。这本书的作者与问题中提到的IBM文章的作者是同一人(事实上,他在那篇文章的末尾引用了他的书)。我对volatile的使用被他的文章称为“模式1状态标志”。

如果您想了解更多关于volatile在底层是如何工作的,请阅读Java内存模型。如果你想超越这个层次,看看像Hennessy & Patterson这样的优秀计算机体系结构书籍,阅读关于缓存一致性和缓存一致性的内容。

Volatile对于停止线程非常有用。

并不是说您应该编写自己的线程,Java 1.6有很多不错的线程池。但是如果你确定你需要一个线程,你需要知道如何停止它。

我使用的线程模式是:

public class Foo extends Thread {

  private volatile boolean close = false;

  public void run() {
    while(!close) {
      // do work
    }
  }
  public void close() {
    close = true;
    // interrupt here if needed
  }
}

在上面的代码段中,while循环中读取close的线程与调用close()的线程不同。如果没有volatile,运行循环的线程可能永远看不到关闭的更改。

注意,这里不需要同步

用volatile关键字声明的变量有两个主要特性,这使得它很特殊。

如果我们有一个易失性变量,它不能被任何线程缓存到计算机的(微处理器)缓存内存中。访问总是发生在主存中。 如果对一个易失性变量正在进行写操作,并且突然请求了一个读操作,那么可以保证写操作将在读操作之前完成。

以上两个品质推断了这一点

所有读取volatile变量的线程肯定会读取最新的值。因为没有缓存值可以污染它。而且读请求只有在当前写操作完成后才会被授予。

另一方面,

如果我们进一步研究我提到的#2,我们可以看到volatile关键字是维护一个共享变量的理想方法,它有n个读线程,只有一个写线程可以访问它。一旦我们添加了volatile关键字,就完成了。没有任何线程安全方面的开销。

交谈,

我们不能仅仅使用volatile关键字来满足有多个写入线程访问它的共享变量。

绝对是的。(不仅是Java, c#也是如此。)有时,您需要获取或设置一个值,该值保证是给定平台上的原子操作,例如int或boolean,但不需要线程锁定的开销。volatile关键字允许您确保在读取值时获得的是当前值,而不是在另一个线程上写入时被废弃的缓存值。

使用volatile的一个常见示例是使用volatile布尔变量作为终止线程的标志。如果您已经启动了一个线程,并且希望能够安全地从另一个线程中断它,您可以让线程定期检查标志。要阻止它,将标志设置为true。通过将标志设置为易失性,可以确保正在检查它的线程在下次检查时看到它已经设置好,甚至不必使用同步块。