在其他线程创建之前初始化C#内存模型和非易失性变量

前端之家收集整理的这篇文章主要介绍了在其他线程创建之前初始化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的实现在这方面可能会有不同的表现.

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关键字.它不仅会使代码线程安全,因为场景变得更复杂,但它也有助于记录该字段将由多个线程使用的事实,并且您已考虑使用锁定的含义 – 免费策略.

猜你在找的C#相关文章