2012-12-18 173 views
4

我在C#多线程程序中遇到了一个不良行为。我的一些静态成员正在其他线程中释放它们的值,而同一个声明类型的一些静态值不会丢失它们的值。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 
      } 

     }); 
    } 
} 

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

+5

通常,可变静态属性不能很好地与并发性兼容。您可能应该限制该状态的范围,或确保在并发访问时不会修改它。 – Servy

+0

感谢您的回复,属性或字段成员?我根据目的在根类中使用了公共字段。 –

+1

我的声明同样适用于属性和字段。它们以某种形式都是可变的公共状态。 – Servy

回答

6

使用volatile变量volatile改性剂或可替代地使用访问交错的变量。

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

为了避免它,你必须确保变量实际上是真正读取的。挥发性做到了。联锁也可以做到这一点(并允许增加/添加等自动发生)。

哪个更好,你必须决定。两者都强制将内存屏障放到处理器上,而且这种处理器经常需要花费不菲的成本。我经常使用的一种模式是让这些对象只读取大部分,以便我只替换根对象(一个内存屏障)。手动处理记忆障碍(可能的话,阅读手册中的关键字)是一个很好的解决办法。不过,它的效率更高 - 取决于你在那里做了多少等等,这可能是需要的。

+1

谢谢,这对我有帮助。 (RTFM在这里为其他人,http://www.albahari.com/threading/part4.aspx)正确的链接。 –

+0

Grats。你刚刚毕业高级程序设计。这取决于代码的复杂程度,可能对于调试非常糟糕。 – TomTom

+0

谢谢,我讨厌的唯一事情就是在高级语言中处理这个东西; P –

2

尝试使用在其上被修改/访问从多个线程

+0

+0。如果从多个线程修改值,'volatile'可能无法帮助。对于“丢失值”的情况绝对不会有帮助,因为它不保证读取大于int32/64的类型的最新值或甚至是consitent值。 –

+1

“'volatile'可能没有帮助,如果值是从多个线程修改”:正是这就是volatile,确保这个变量是真正更新每个线程试图访问它。 – VladL

+1

(BTW所有这些不稳定/互锁与OP问题无关:))。其实你是对的 - 我的看法并不完全正确('挥发性'给你当前的价值,但没有办法确保价值没有改变)。 OP案例不同 - 包含两个单独更新的字段 - 在这种情况下没有任何可以标记为“volatile”的东西可以提供一致的行为。 –

0

多线程应用程序中的共享变量值不确定!您应该在每个共享资源上使用锁定以避免逻辑中的冲突:

static Readonly Object _lock=new Object(); 
    lock(_lock) 
    { 
    //accessing your shared variable 
    }