我需要在C#.Net中创建一个Thread安全的静态变量

Sto*_*orm 11 c# static thread-safety

好吧,它比问题复杂一点.

class A
{
   static int needsToBeThreadSafe = 0;

   public static void M1()
   {
     needsToBeThreadSafe = RandomNumber();
   }

   public static void M2()
   {
     print(needsToBeThreadSafe);
   }
}
Run Code Online (Sandbox Code Playgroud)

现在我要求在M1()和M2()之间调用'needsToBeThreadSafe'保持线程安全.

小智 21

怎么样:

public static void M1()
{
    Interlocked.Exchange( ref needsToBeThreadSafe, RandomNumber() );
}

public static void M2()
{
    print( Interlocked.Read( ref needsToBeThreadSafe ) );
}
Run Code Online (Sandbox Code Playgroud)


par*_*cle 19

您可能要问的是[ ThreadStatic ]属性.如果您希望每个使用该类的线程A都有自己独立的值,needsToBeThreadSafe那么您只需要使用[ ThreadStatic ]属性来装饰该字段.

有关详细信息,请参阅MSDN文档ThreadStaticAttribute.

  • 好的,但ThreadStatic不是ThreadSafe. (5认同)
  • 我**得到你的积分,我不想不必要地扩展对话,但我对"线程安全"的理解是,如果一段代码在多线程下同时运行是安全的."线程局部存储"是该定义的一个简单实现,如果您确实需要共享数据,可能无法满足您的需求.如果您需要的是多个执行线程,而没有线程踩到彼此的脚,并且"线程本地存储"满足您的需求,那么它就是最佳选择.此外,维基百科的文章(http://en.wikipedia.org/wiki/Thread_safety)似乎也同意我的看法. (5认同)

Ada*_*son 8

您有两种选择:给出您提供的代码最简单的是volatile关键字.声明needsToBeThreadSafestatic volatile int,这将保证引用该变量的任何线程都将获得"最新"副本,并且该变量不会缓存在您的代码中.

话虽这么说,如果你想更一般地确保M1()M2()"原子地"(或至少完全相互)执行,那么你想要使用lock.最干净的语法是使用"锁定块",如下所示:

private static object locker = new Object();

//..

public static void M1()
{
    lock(locker)
    {
        //..method body here
    }
}

public static void M2()
{
    lock(locker)
    {
        //..method body here
    }
}
Run Code Online (Sandbox Code Playgroud)

至于采取哪种方法,这取决于你,应该由代码决定.如果你只需要确保成员赋值传播到所有线程并且没有缓存,那么volatile关键字就更简单了,并且可以很好地完成工作.如果超出这个范围,你可能想要去lock.