class A
{
static int needsToBeThreadSafe = 0;
public static void M1()
{
needsToBeThreadSafe = RandomNumber();
}
public static void M2()
{
print(needsToBeThreadSafe);
}
}
现在我要求在M1()和M2()之间调用'needsToBeThreadSafe'保持线程安全。
答案 0 :(得分:21)
如何:
public static void M1()
{
Interlocked.Exchange( ref needsToBeThreadSafe, RandomNumber() );
}
public static void M2()
{
print( Interlocked.Read( ref needsToBeThreadSafe ) );
}
答案 1 :(得分:19)
您可能要问的是[ ThreadStatic ]属性。如果您希望使用 A
类的每个线程都有自己独立的 needsToBeThreadSafe
值,那么您只需要使用[ ThreadStatic ]属性。
有关详细信息,请参阅MSDN documentation for ThreadStaticAttribute
。
答案 2 :(得分:8)
您有两种选择:给出您提供的代码最简单的是volatile
关键字。将needsToBeThreadSafe
声明为static volatile int
,这将保证引用该变量的任何线程都将获得“最新”副本,并且该变量不会缓存在您的代码中。
话虽如此,如果你想更一般地确保M1()
和M2()
“原子地”执行(或者至少完全相互执行),那么你想要使用{{1} }。最干净的语法是使用“锁定块”,如下所示:
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
}
}
关键字就更简单了,并且可以很好地完成工作。如果超出此范围,您可能需要使用volatile
。
答案 3 :(得分:4)
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);
}
}
}
答案 4 :(得分:2)
听起来你需要Volatile成员。
static volatile int needsToBeThreadSafe = 0;
答案 5 :(得分:2)
您还可以使用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();
}
}
答案 6 :(得分:2)
首先,我同意使用lock()
的答案,这是最安全的方式。
但是存在一种更简约的方法,您的示例代码仅显示使用needsToBeThreadSafe
的单个语句,并且因为 int
是原子的,您只需要阻止编译器使用缓存易失性:
class A
{
static volatile int needsToBeThreadSafe = 0;
}
但如果你需要在多个语句中使用toTeTereadSafe作为'ThreadSafe',请使用锁。