.Net POCO的线程安全吗?

时间:2011-04-10 13:01:35

标签: c# .net concurrency thread-safety visibility

这个问题似乎有些奇怪,但与可能的可见性问题有关。问题的灵感来自Java编程语言(> jdk5)中的一个案例,请考虑:

public class InmutableValue {
  private int value;
  public InmutableValue(int value) {this.value = value;}
  public int getValue() {return value;}
}

尽管有相反的信念,但上述课程并非线程安全。在多线程环境中,不保证其他线程可以看到“值”。为了使其成为线程安全的,我们需要强制实施“先发生”规则。这可以通过标记“最终”字段来实现。

这个案例让我想知道.Net运行时是否也是如此。举个例子来说:

public class InmutableValue {
  private int value;
  public InmutableValue(int value) {this.value = value;}
  public int Value { get{return value;}}
} 

据我所知,将值字段标记为'readonly'并不能提供与'final'对java相同的保证(但我可能非常错误,希望如此)。那么我们是否需要将字段标记为“易变”(或使用内存屏障等)以确保其他线程的可见性?或者是否有其他规则可以确保可见性?

2 个答案:

答案 0 :(得分:2)

你可能会担心内存模型较弱的cpu内核,比如Alpha和Titanium。它有一个内存写缓冲区,可以重新排序内存写入,使得可以在字段值之前写入对象引用。也许灵感来自Raymond Chen的博客?

你错过了一个重要的细节。要创建线程竞争,必须有两个使用对象引用的线程。一个创建对象并存储引用,另一个使用该引用。 基本上是线程不安全的,需要同步对共享对象引用的访问。同步代码(如 lock 语句)也可确保刷新回写缓冲区。这可以防止读取属性的线程看到过时的值。

答案 1 :(得分:1)

无论如何,readonly关键字只能确保在构造函数中分配字段,而不是在其他任何地方(在类内)。

就构造函数为thread-safe in general meaning而言,一旦创建对象将返回相同的值:

static ImmutableValue imv = new ImmutableValue(123);

// thread 1, object is not created
imv.Value; // NullReferenceException, as usually

// thread 2, object is created
imv.Value; //123

// thread 3, object is created
imv.Value; //123

要编辑private字段,您需要使用Reflection,是的,您需要在此类代码执行期间锁定对象,以保证冻结此时尝试读取值的所有线程。

相关问题