在其他线程创建之前初始化C#内存模型和非易失性变量
我有一个与C#内存模型和线程有关的问题.如果没有volatile关键字,我不确定以下代码是否正确.
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中的相同代码怎么样? 谢谢,米哈尔 解决方法
有很多地方会创建隐式内存障碍.这是其中之一.启动线程创建完全障碍.因此,对变量A的写入将在线程启动之前提交,并且将从主存储器获取第一次读取.当然,在微软的CLR实现中,这有点不成比例,因为写入已经具有易失性语义.但是ECMA规范中没有提出相同的保证,因此理论上可能Mono的实现在这方面可能会有不同的表现.
在这种情况下……是的.但是,如果您继续在第二个线程中使用variableA,则在第一次读取后没有保证,它将看到更新.
是.
是的,但仅限于第一次阅读.
在这个非常具体和狭窄的情况下……没有.但是,通常建议您在这些场景中使用volatile关键字.它不仅会使代码线程安全,因为场景变得更复杂,但它也有助于记录该字段将由多个线程使用的事实,并且您已考虑使用锁定的含义 – 免费策略. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |