我给自己写了一个多线程随机生成器
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字段是不是被禁止了?
我知道我可以检查字段是否每次都被初始化,但这不是我想要的解决方案。
发布于 2013-08-07 01:18:34
初始化ThreadStatic字段有点棘手。特别要注意的是:
不会为标记为ThreadStaticAttribute的字段指定初始值,因为此类初始化只在类构造函数执行时发生一次,因此只影响一个线程。
在MSDN Docs中。这意味着在初始化类时运行的线程将获得您在字段声明中定义的初始值,但所有其他线程的值都将为null。我认为这就是为什么你的代码会表现出你问题中描述的不受欢迎的行为。
更完整的解释在this blog中。
(摘自博客)
[ThreadStatic]
private static string Foo = "the foo string";在静态构造函数中初始化ThreadStatic -该构造函数只执行一次。因此,当静态构造函数执行时,只有第一个线程被分配了“foo字符串”。当在所有后续线程中访问时,Foo将保留未初始化的空值。
解决这个问题的最好方法是使用属性来访问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
发布于 2019-06-08 07:43:42
关于问题的原因,前面的答案是正确的。
如果您可以使用.NET 4或更高版本,请使用ThreadLocal,因为它是通过初始化器构建的。
请参阅ThreadStatic v.s. ThreadLocal: is generic better than attribute?
这样你就不需要在每次读取时都进行访问器重载或null检查。
https://stackoverflow.com/questions/18086235
复制相似问题