你有没有在Java中使用volatile关键字?

在今天的工作中,我遇到了Java中的volatile关键字。 不太熟悉它,我找到了这样的解释:

Java理论与实践:管理波动性

考虑到该文章解释关键字的详细信息,您是否曾经使用过该关键字,或者您是否曾经看到可以正确使用此关键字的情况?


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

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

本书强烈推荐的“Java Concurrency in Practice”一书给出了volatile一个很好的解释。 本书是由编写问题中引用的IBM文章的同一人撰写的(实际上,他在该文章的底部引用了他的书)。 我对volatile使用就是他的文章所称的“模式1状态标志”。

如果你想了解更多关于如何volatile工作,请阅读Java内存模型。 如果你想超越这个水平,请查看像Hennessy&Patterson这样的好计算机体系结构书,并阅读关于缓存一致性和缓存一致性的内容。


“... volatile修饰符保证读取字段的任何线程都能看到最近写入的值。” - Josh Bloch

如果您正在考虑使用volatile ,请阅读处理原子行为的java.util.concurrent包。

单身模式上的维基百科发布显示使用中不稳定。


关于volatile的重要一点:

  • Java中的同步可以通过使用Java关键字synchronizedvolatile
  • 在Java中,我们不能有synchronized变量。 对变量使用synchronized关键字是非法的,将导致编译错误。 可以使用java volatile变量来代替在Java中使用synchronized变量,该变量将指示JVM线程从主内存中读取volatile变量的值,并且不会在本地缓存它。
  • 如果多个线程之间不共享变量,则不需要使用volatile关键字。
  • 资源

    volatile的使用示例:

    public class Singleton {
        private static volatile Singleton _instance; // volatile variable
        public static Singleton getInstance() {
            if (_instance == null) {
                synchronized (Singleton.class) {
                    if (_instance == null)
                        _instance = new Singleton();
                }
            }
            return _instance;
        }
    }
    

    在第一次请求发布时,我们正在懒惰地创建实例。

    如果我们不将_instance变量设置为volatile那么创建Singleton实例的Thread将无法与其他线程通信。 因此,如果线程A正在创建Singleton实例并且在创建之后,CPU就会破坏等等,所有其他线程将不能将_instance的值看作非空值,并且他们会认为它仍然被赋值为空。

    为什么会发生? 由于读线程线程没有进行任何锁定,并且在写线程从同步块出来之前,内存将不会同步,并且_instance值不会在主内存中更新。 通过Java中的Volatile关键字,这由Java本身处理,所有读者线程都可以看到这些更新。

    结论volatile关键字也用于在线程之间传递内存内容。

    不使用volatile的示例用法:

    public class Singleton{    
        private static Singleton _instance;   //without volatile variable
        public static Singleton getInstance(){   
              if(_instance == null){  
                  synchronized(Singleton.class){  
                   if(_instance == null) _instance = new Singleton(); 
          } 
         }   
        return _instance;  
        }
    

    上面的代码不是线程安全的。 虽然它在同步块内再次检查实例的值(出于性能原因),但JIT编译器可以重新排列字节码,以便在构造函数完成其执行之前设置对实例的引用。 这意味着getInstance()方法返回一个可能尚未完全初始化的对象。 为了让代码是线程安全的,关键字volatile可以在Java 5以后用于实例变量。 标记为volatile的变量只有在对象的构造函数完成完成后才会被其他线程看到。
    资源

    在这里输入图像描述

    java中非易失性使用快速迭代器通常使用列表对象上的volatile计数器来实现。

  • 当列表更新时,计数器递增。
  • 当创建Iterator ,计数器的当前值被嵌入到Iterator对象中。
  • 当执行Iterator操作时,该方法会比较两个计数器值,如果它们不同则抛出ConcurrentModificationException
  • 故障安全迭代器的实现通常是轻量级的。 它们通常依赖于特定列表实现的数据结构的属性。 没有一般的模式。

    链接地址: http://www.djcxy.com/p/96517.html

    上一篇: Do you ever use the volatile keyword in Java?

    下一篇: How to add custom items to QFileDialog?