Полезно, если Вы хотите разделить выделение от инициализации. STL использует размещение, новое для создания контейнерных элементов.
Возможно, вы пытаетесь спросить об атрибуте [ ThreadStatic ]. Если вы хотите, чтобы каждый поток, использующий класс A
, имел собственное отдельное значение needsToBeThreadSafe
, вам просто нужно украсить это поле атрибутом [ ThreadStatic ]. .
Дополнительные сведения см. В документации MSDN для ThreadStaticAttribute
.
У вас есть два варианта: самый простой из представленных вами кодов - это ключевое слово volatile
. объявите needsToBeThreadSafe
как static volatile int
, и это будет гарантировать, что любой поток, который ссылается на эту переменную, получит «последнюю» копию, а переменная не будет кэшироваться в вашем коде.
При этом, если вы хотите в более общем плане гарантировать, что M1 ()
и M2 ()
выполняются «атомарно» (или, по крайней мере, исключительно друг от друга), тогда вам нужно использовать блокировку
. Самый чистый синтаксис - это «блокирующий блок», например:
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
проще и отлично справится с этой задачей. Если это не так, вы можете использовать блокировку
.
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);
}
}
}
Похоже, вам нужен член Volatile .
static volatile int needsToBeThreadSafe = 0;
Вы также можете использовать 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();
}
}
Для начала я согласен с ответами, используя lock ()
, это самый безопасный способ.
Но существует более минималистичный подход, в вашем примере кода отображается только один операторы, использующие needsToBeThreadSafe
, и поскольку int
является атомарным, вам нужно только предотвратить кеширование компилятором с использованием volatile:
class A
{
static volatile int needsToBeThreadSafe = 0;
}
Но если вам нужно, чтобы needToBeThreadSafe было «ThreadSafe» по нескольким операторам, используйте замок.