我需要在 C# .Net 中创建一个线程安全的静态变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1254750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
I need to create a Thread-safe static variable in C# .Net
提问by Storm
ok, its a little more complicated than the question.
好吧,它比问题复杂一点。
class A
{
static int needsToBeThreadSafe = 0;
public static void M1()
{
needsToBeThreadSafe = RandomNumber();
}
public static void M2()
{
print(needsToBeThreadSafe);
}
}
now i require that between M1() and M2() calls 'needsToBeThreadSafe' stays Thread Safe.
现在我要求 M1() 和 M2() 调用之间的“needsToBeThreadSafe”保持线程安全。
采纳答案by paracycle
What you might be trying to ask about is the [ThreadStatic] attribute. If you want each thread that uses the class A
to have its own separate value of needsToBeThreadSafe
then you just need to decorate that field with the [ThreadStatic] attribute.
您可能要问的是 [ ThreadStatic] 属性。如果您希望使用该类的每个线程A
都有自己单独的值,needsToBeThreadSafe
那么您只需要使用 [ ThreadStatic] 属性装饰该字段。
For more info refer to the MSDN documentation for ThreadStaticAttribute
.
有关更多信息,请参阅MSDN 文档ThreadStaticAttribute
。
回答by Arsen Mkrtchyan
class A
{
static int needsToBeThreadSafe = 0;
static object statObjLocker = new object();
public static void M1()
{
lock(statObjLocker)
{
needsToBeThreadSafe = RandomNumber();
}
}
public static void M2()
{
lock(statObjLocker)
{
print(needsToBeThreadSafe);
}
}
}
回答by Adam Robinson
You have two choices: the easiest given your presented code is the volatile
keyword. declare needsToBeThreadSafe
as static volatile int
and that will guarantee that any thread that references that variable will get the "latest" copy, and the variable won't be cached within your code.
您有两种选择:最简单的给您呈现的代码是volatile
关键字。声明needsToBeThreadSafe
为static volatile int
,这将保证引用该变量的任何线程都将获得“最新”副本,并且该变量不会被缓存在您的代码中。
That being said, if you want to more generally ensure that M1()
and M2()
execute "atomically" (or at least exclusively of each other), then you want to use a lock
. The cleanest syntax is with a "lock block", like this:
话虽如此,如果您想更普遍地确保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
}
}
As to which approach to take, that's up to you and should be determined by the code. If all you need is to ensure that a member assignment gets propagated to all threads and isn't cached, then the volatile
keyword is simpler and will do the job just fine. If it's beyond that, you may want to go with the lock
.
至于采用哪种方法,这取决于你,应该由代码决定。如果您只需要确保成员分配被传播到所有线程并且不被缓存,那么volatile
关键字就更简单并且可以很好地完成工作。如果超出此范围,您可能想要使用lock
.
回答by C. Ross
回答by HuBeZa
You can also use the ReaderWriterLockSlim, that is more efficient for multiple reads and less writes:
您还可以使用 ReaderWriterLockSlim,它对于多读少写更有效:
static int needsToBeThreadSafe = 0;
static System.Threading.ReaderWriterLockSlim rwl = new System.Threading.ReaderWriterLockSlim();
public static void M1()
{
try
{
rwl.EnterWriteLock();
needsToBeThreadSafe = RandomNumber();
}
finally
{
rwl.ExitWriteLock();
}
}
public static void M2()
{
try
{
rwl.EnterReadLock();
print(needsToBeThreadSafe);
}
finally
{
rwl.ExitReadLock();
}
}
回答by Henk Holterman
To start with I agree with the answers using lock()
, that is the safest way.
首先,我同意使用 的答案lock()
,这是最安全的方法。
But there exists a more minimalist approach, your sample code only shows single statements using needsToBeThreadSafe
and since int
is atomic you only need to prevent caching by the compiler using volatile:
但是存在更简约的方法,您的示例代码仅显示单个语句使用,needsToBeThreadSafe
并且由于int
是原子的,您只需要使用 volatile 防止编译器缓存:
class A
{
static volatile int needsToBeThreadSafe = 0;
}
But if you need needsToBeThreadSafe to be 'ThreadSafe' over multiple statements, use a lock.
但是,如果您需要将 NeedToBeThreadSafe 用于多个语句的“ThreadSafe”,请使用锁。
回答by cosmo
How About:
怎么样:
public static void M1()
{
Interlocked.Exchange( ref needsToBeThreadSafe, RandomNumber() );
}
public static void M2()
{
print( Interlocked.Read( ref needsToBeThreadSafe ) );
}