据我所知,如果我们将变量声明为volatile,那么它将不会存储在本地缓存中.每当线程更新值时,它都会更新到主存储器.因此,其他线程可以访问更新的值.
但是在下面的程序中,volatile和non-volatile变量都显示相同的值.
不会为第二个线程更新volatile变量.任何人都可以解释为什么testValue没有改变.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
output:
Thread 1 testValue1 : 10
Thread 1 testValue : 10
Thread 2 testValue1 : 0
Thread 2 testValue : 0
Run Code Online (Sandbox Code Playgroud)
您的变量仅限于一个线程,因此没有其他线程访问它们.因此volatile没有区别.
如果您声明了它们static,它们将在不同的线程之间共享.但是,即使这样,您也可能无法观察到易失性和非易失性变量之间的差异.引自Java Concurrency in Practice,第二章.3.1.4:
volatile变量的可见性效果超出了volatile变量本身的值.当线程A写入易失性变量并且随后线程B读取相同的变量时,在写入易失性变量之前,A可见的所有变量的值在读取volatile变量后变为B可见.因此,从内存可见性的角度来看,编写volatile变量就像退出synchronized块一样,读取volatile变量就像进入synchronized块一样.
在您的情况下,代码首先修改volatile变量,因此另一个变量的更新值可能对另一个线程不可见.到现在为止还挺好.
但是,由于您要从修改它们的同一个线程中打印出变量的值,因此无论如何都不会看到任何差异.
Update2:试试这个修改过的版本(注意:我还没有测试过):
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();
}
}
Run Code Online (Sandbox Code Playgroud)
更新:关于静态字段的可见性 - 再次来自同一个主题(第16.2.3节):
[...]静态初始化的对象在构造期间或被引用时不需要显式同步.但是,这仅适用于构造状态 - 如果对象是可变的,则读取器和写入器仍然需要同步以使后续修改可见并避免数据损坏.
| 归档时间: |
|
| 查看次数: |
1495 次 |
| 最近记录: |