我对volatile关键字的行为有疑问。
public class TestClassI extends Thread {
private volatile int i=5;
boolean flag;
public TestClassI( boolean flag) {
this.i=i;
this.flag=flag;
}
public void run()
{
if(flag)
{
while(true)
{
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
else
{
i=10;
}
}
}
在主要课程中使用as
public class TestMain {
public static volatile int i=5;
public static void main(String args[]) throws InterruptedException
{
TestClassI test= new TestClassI( true);
test.start();
Thread.sleep(1000);
TestClassI test2=new TestClassI( false);
test2.start();
}
}
我预计价值会是这样的 五 五 五 五 10 10 10 10。 但是它继续给出5.但是每次我应该从主存储器中存储和检索i的易变性值的asper性质。请解释这段代码有什么问题吗?
答案 0 :(得分:3)
您有两个TestClassI
个实例。它们各自都有自己的i
版本(因为它是一个实例字段)。它们完全不会干扰彼此。
程序中根本没有使用静态TestMain.i
。没有共享状态。
答案 1 :(得分:0)
当使用false标志对象进行实例化时,run方法将i
初始化为10,然后返回。永远不会打印i
:
if (flag) {
// irrelevant
}
else {
i = 10;
}
答案 2 :(得分:0)
您没有在循环中设置i=10
,因此它将被设置为您帖子中的唯一操作,但从不打印...
答案 3 :(得分:-2)
volatile
变量在这种情况下无效,因为变量是int
。 long
和double
变量受volatile
影响,它们被加载并存储在一个操作中,该操作不能被中断而不是两个,每个单词一个。所以volatile
变量没有效果。
产生异常输出的情况是,i
不会在您的线程之间共享。如果你看,每个线程都有一个单独的i
,尽管主类中有一个静态i
。仅供参考,主要类中的i
没有被线程忽视,他们根本没有注意到它。如果你想让它工作,一个简单的修改就足够了:让线程中的i
变量保持静态。不在主类中,在线程中。