使用volatile关键字 [英] using volatile keyword

查看:106
本文介绍了使用volatile关键字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,如果我们将变量声明为volatile,那么它将不会存储在本地缓存中。每当线程更新值时,它都会更新到主存储器。因此,其他线程可以访问更新的值。

As i understand, if we declare a variable as volatile, then it will not be stored in the local cache. Whenever thread are updating the values, it is updated to the main memory. So, other threads can access the updated value.

但是在下面的程序中,volatile和non-volatile变量都显示相同的值。

But in the following program both volatile and non-volatile variables are displaying same value.

volatile变量没有为第二个线程更新。
任何人都可以解释为什么testValue没有改变。

The volatile variable is not updated for the second thread. Can anybody plz explain this why testValue is not changed.

class ExampleThread extends Thread {
    private int testValue1;
    private volatile int testValue;
    public ExampleThread(String str){
      super(str);
    }
    public void run() {
    if (getName().equals("Thread 1 "))
    {
        testValue = 10;
        testValue1= 10;
        System.out.println( "Thread 1 testValue1 : " + testValue1);
        System.out.println( "Thread 1 testValue : " + testValue);
    }
    if (getName().equals("Thread 2 "))
    {
        System.out.println( "Thread 2 testValue1 : " + testValue1);
        System.out.println( "Thread 2 testValue : " + testValue);
    }               
}
}

public class VolatileExample {
    public static void main(String args[]) {
        new ExampleThread("Thread 1 ").start();
        new ExampleThread("Thread 2 ").start();
    }
}


output:
Thread 1 testValue1 : 10
Thread 1 testValue : 10
Thread 2 testValue1 : 0
Thread 2 testValue : 0


推荐答案

您的变量仅限于单线程,因此没有其他线程访问它们。因此 volatile 没有区别。

Your variables are confined to a single thread, so there is no other thread accessing them. Thus volatile makes no difference.

如果你声明它们 static ,它们将在不同的线程之间共享。但是,即使这样,您也可能无法观察到易失性和非易失性变量之间的差异。引自 Java Concurrency in Practice ,第二章。 3.1.4:

If you declared them static, they would be shared between different threads. However, even then you may not be able to observe the difference between your volatile and nonvolatile variable. Quote from Java Concurrency in Practice, chap. 3.1.4:


volatile变量的可见性效果超出了volatile变量本身的值。当线程A写入volatile变量并且随后线程B读取同一个变量时,在写入volatile变量之前,A可见的所有变量的值在读取volatile变量后变为B可见。因此,从内存可见性的角度来看,编写volatile变量就像退出synchronized块一样,读取volatile变量就像进入synchronized块一样。

The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. So from a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block.

在您的情况下,代码首先修改volatile变量,因此另一个变量的更新值可能对另一个线程不可见。到目前为止,非常好。

In your case, the code happens to modify the volatile variable first, so the updated value of the other variable may not be visible to the other thread. So far, so good.

但是,由于您要从修改它们的同一个线程中打印出变量的值,无论如何都看不出任何差异。

However, since you are printing out the values of the variables from the same thread which modified them, you won't see any difference anyway.

Update2:试试这个修改过的版本(注意:我还没有测试过):

Update2: Try this modified version (note: I have not tested it):

class ExampleThread extends Thread {
    private static int testValue1;
    private static volatile int testValue;
    private int newValue;

    public ExampleThread(String str, int newValue){
      super(str);
      this.newValue = newValue;
    }
    public void run() {
      for (int i = 0; i < 10; i++) {
        System.out.println(getName() + " testValue1 before update: " + testValue1);
        System.out.println(getName() + " testValue before update: " + testValue);
        testValue = i * newValue;
        testValue1 = i * newValue;
        System.out.println(getName() + " testValue1 after update: " + testValue1);
        System.out.println(getName() + " testValue after update: " + testValue);
        sleep(10);
      }               
    }               
}

public class VolatileExample {
    public static void main(String args[]) {
        new ExampleThread("Thread 1 ", 5).start();
        new ExampleThread("Thread 2 ", 10).start();
    }
}

更新:关于静态字段的可见性 - 再次来自同一个主题(第16.2.3节):

Update: regarding the visibility of static fields - again from the same tome (chap 16.2.3):


[...]静态初始化的对象不需要显式在构造期间或被引用时同步。但是,这仅适用于 as-construct 状态 - 如果对象是可变的,则读者和编写者仍然需要同步以使后续修改可见并避免数据损坏。

[...] statically initialized objects require no explicit synchronization either during construction or when being referenced. However, this applies only to the as-constructed state - if the object is mutable, synchronization is still required by both readers and writers to make subsequent modifications visible and to avoid data corruption.

这篇关于使用volatile关键字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆