c# - 初始化 ThreadStatic 字段仍然导致 NullReferenceException

标签 c# random thread-safety threadstatic

我自己写了一个多线程随机生成器

public static class MyRandGen
{
    private static Random GlobalRandom = new Random();
    [ThreadStatic]
    private static Random ThreadRandom = new Random(SeedInitializer());
    private static int SeedInitializer()
    {
        lock (GlobalRandom) return GlobalRandom.Next();
    }

    public static int Next()
    {
        return ThreadRandom.Next();
    }
}

但是,它在触发 Next() 时抛出一个 NullReferenceException,我不明白。是否以某种方式禁止初始化 ThreadStatic 字段?

我知道我可以每次都检查该字段是否已初始化,但这不是我正在寻找的解决方案。

最佳答案

初始化 ThreadStatic 字段有点棘手。特别是有这个警告:

Do not specify initial values for fields marked with ThreadStaticAttribute, because such initialization occurs only once, when the class constructor executes, and therefore affects only one thread.

MSDN Docs .这意味着在初始化类时运行的线程获得您在字段声明中定义的初始值,但所有其他线程的值为 null。我认为这就是为什么您的代码表现出问题中描述的不良行为的原因。

更完整的解释在 this blog 中.

(来自博客的片段)

[ThreadStatic]
private static string Foo = "the foo string";

The ThreadStatic is initialized in the static constructor - which only executes once. So only the very first thread is assigned "the foo string" when the static constructor executes. When accessed in all subsequent threads, Foo is left at the uninitalized null value.

The best way to work around this is to use a property to access the Foo prop.

[ThreadStatic]
private static string _foo;

public static string Foo {
   get {
     if (_foo == null) {
         _foo = "the foo string";
     }
     return _foo;
   }
}

请注意,不需要在静态属性中加锁,因为每个线程都作用于仅供该线程使用的 _foo。不能与其他线程争用。这包含在这个问题中:ThreadStatic and Synchronization

关于c# - 初始化 ThreadStatic 字段仍然导致 NullReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18086235/

相关文章:

c# - 在 C# 中以编程方式从数据库创建 XSD

c# - 继承类属性中的属性差异

c# - 如何将 DateTimePicker 设置为特定时间并保持自定义日期?

c# webrequest 挂起

javascript - div 的随机位置和悬停功能

c++ - 由于新的 const,C++11 对象在多线程环境中可能会变慢吗?

multithreading - “free-threaded”和 “thread-safe”之间的区别

python - 排除 random.choice() 生成的特定字符

arrays - 如何从 Julia 的加权数组中选择随机项?

java - 这个 Singleton 是线程安全的吗?我看不出来怎么办?