gpt4 book ai didi

C# 跨线程静态变量访问

转载 作者:太空狗 更新时间:2023-10-29 20:07:55 25 4
gpt4 key购买 nike

我在 C# 多线程程序中遇到不良行为。我的一些静态成员在其他线程中丢失了它们的值,而相同声明类型的一些静态成员没有丢失它们的值。

public class Context {
public Int32 ID { get; set; }
public String Name { get; set; }

public Context(Int32 NewID, String NewName){
this.ID = NewID;
this.Name = NewName;
}
}

public class Root {
public static Context MyContext;
public static Processor MyProcessor;

public Root(){
Root.MyContext = new Context(1,"Hal");

if(Root.MyContext.ID == null || Root.MyContext.ID != 1){
throw new Exception("Its bogus!") // Never gets thrown
}

if(Root.MyContext.Name == null || Root.MyContext.Name != "Hal"){
throw new Exception("It's VERY Bogus!"); // Never gets thrown
}

Root.MyProcessor = new MyProcessor();
Root.MyProcessor.Start();
}
}

public class Processor {
public Processor() {
}

public void Start(){
Thread T= new Thread (()=> {

if(Root.MyContext.Name == null || Root.MyContext.Name != "Hal"){
throw new Exception("Ive lost my value!"); // Never gets Thrown
}

if(Root.MyContext.ID == null){
throw new Exception("Ive lost my value!"); // Always gets thrown
}

});
}
}

这是使用某些类型的静态成员时的线程突变问题吗?

最佳答案

使用 volatile 或使用 Interlocked 访问变量。

您遇到的问题是编译器(以及 native 编译器)可以自由地优化对变量的访问,因为他认为没有变量是合适的。所以他可能会将一个变量转储到寄存器中,而不是重新读取它。

为了避免这种情况,您必须确保变量确实被真正地读取了。 volatile 就是这样做的。 Interlocked 也这样做(并允许增量/添加等以原子方式发生)。

您必须决定哪个更好。两者都将内存屏障强加到处理器上,如果经常这样做,这确实会产生不小的成本。我经常使用的一种模式是让这些对象大部分只读,这样我就只替换根对象(一个内存屏障)。手动处理内存障碍(可能,请阅读关键字手册)很难正确处理。不过,它的效率要高得多 - 取决于您在那里做了多少等等。可能需要它。

关于C# 跨线程静态变量访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13939976/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com