根据:
http://www.ibm.com/developerworks/library/j-jtp03304/
在新的内存模型下,当线程A写入易失性变量V,并且线程B从V读取时,在写入V时对A可见的任何变量值现在都保证对B可见.
互联网上的许多地方声明以下代码永远不应该打印"错误":
public class Test {
volatile static private int a;
static private int b;
public static void main(String [] args) throws Exception {
for (int i = 0; i < 100; i++) {
new Thread() {
@Override
public void run() {
int tt = b; // makes the jvm cache the value of b
while (a==0) {
}
if (b == 0) {
System.out.println("error");
}
}
}.start();
}
b = 1;
a = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
b …
我对线程概念还很陌生,并尝试更多地了解它.最近,我发现了一篇关于Jeremy Manson撰写的" Java中的易失手段"的博客文章,他写道:
当一个线程写入一个volatile变量,而另一个线程看到该写入时,第一个线程告诉第二个线程关于内存的所有内容,直到它执行对该volatile变量的写入.[...] 所有的由线程1看到的存储内容,才写信给
[volatile] ready
,必须是可见的主题2,它读取值后true
进行ready
.[自己强调]
现在,这是否意味着在写入volatile变量时,线程1的内存中保存的所有变量(volatile或not)将在读取volatile变量后变为可见?如果是这样,是否可以从官方Java文档/ Oracle源代码中将该语句拼凑起来?从哪个版本的Java开始这个工作?
特别是,如果所有线程共享以下类变量:
private String s = "running";
private volatile boolean b = false;
Run Code Online (Sandbox Code Playgroud)
并且线程1首先执行以下操作:
s = "done";
b = true;
Run Code Online (Sandbox Code Playgroud)
然后线程2执行(在线程1写入volatile字段之后):
boolean flag = b; //read from volatile
System.out.println(s);
Run Code Online (Sandbox Code Playgroud)
这会保证打印"完成"吗?
如果我将写入和读取放入块中而不是声明b
,会发生什么?volatile
synchronized
另外,在题为" 线程之间是否共享静态变量? "的讨论中,@ TREE 写道:
不要使用volatile来保护多个共享状态.
为什么?(对不起;我还没有就其他问题发表评论,或者我会在那里问过......)
我最近在一次演讲中听到,写入volatile会触发线程写入的每个变量的内存屏障.这是真的正确吗?从JLS看来,似乎只有相关的变量才被刷新,而其他变量则没有.有人知道什么是正确的吗?能指出我在JLS的具体位置吗?
我试图理解volatile变量的工作.我创建了一个简单的类"A",它扩展了"Thread"并具有一个volatile变量"i".还有另一个类"Amain"运行3个"A"类线程.我在A的run()中运行一个循环,它取决于这个volatile变量.这里的代码.
// Thread
public class A extends Thread {
public volatile int i = 0;
@Override
public void run() {
while(i<10)
System.out.println(i++ + " " + this.getName());
}
}
// Main Class
public class Amain {
public static void main(String[] args) {
A t1 = new A();
A t2 = new A();
A t3 = new A();
t1.start();
t2.start();
t3.start();
}
}
Run Code Online (Sandbox Code Playgroud)
如果在所有线程之间共享易失性值,那么"i"应该被打印10次.相反,它为每个线程打印10个值,即总共30个值.需要在此代码的上下文中理解volatile的工作.另外,我还可以从任意数量的线程中获取i的10个值(在此代码的上下文中).