public class A { private int variableA = 0; public A() { variableA = 1; Thread B = new Thread(new ThreadStart(() => printA())).Start(); } private void printA() { System.Console.WriteLine(variableA); } }
我担心的是,如果保证线程B在不使用volatile的情况下看到变量A值为1?在主线程中,我只在构造函数中为variableA赋值1.之后我没有触及变量A,它只在线程B中使用,因此可能不需要锁定.
但是,是否保证主线程将刷新其缓存并将variableA内容写入主内存,因此第二个线程可以读取新分配的值?
另外,是否保证第二个线程将从主存中读取变量A的内容?可能会发生一些编译器优化,并且线程B可以从缓存而不是主内存中读取变量A内容吗?当指令的顺序改变时,可能会发生这种情况.
当然,将volatile添加到variableA声明将使代码正确.但是,它是否必要?我问,因为我在构造函数中编写了一些非易失性变量初始化的代码,稍后某些Timer线程使用这些变量,我不确定它是否完全正确.
Java中的相同代码怎么样?
谢谢,米哈尔
解决方法
My concern is if it is guaranteed that
the Thread B will see variableA with
value 1 without using volatile?
在这种情况下……是的.但是,如果您继续在第二个线程中使用variableA,则在第一次读取后没有保证,它将看到更新.
But,is it guaranteed that the main
thread will flush his cache and write
the variableA contents to the main
memory,so the second thread can read
the newly assigned value?
是.
Additionally,is it guaranteed that
the second thread will read the
variableA contents from the main
memory?
是的,但仅限于第一次阅读.
For sure,adding volatile to the
variableA declaration will make the
code correct. But,is it neccessary?
在这个非常具体和狭窄的情况下……没有.但是,通常建议您在这些场景中使用volatile关键字.它不仅会使代码线程安全,因为场景变得更复杂,但它也有助于记录该字段将由多个线程使用的事实,并且您已考虑使用锁定的含义 – 免费策略.