Я должен создать Ориентированную на многопотоковое исполнение статическую переменную в .NET C#

Полезно, если Вы хотите разделить выделение от инициализации. STL использует размещение, новое для создания контейнерных элементов.

11
задан pupeno 10 August 2009 в 13:05
поделиться

6 ответов

Возможно, вы пытаетесь спросить об атрибуте [ ThreadStatic ]. Если вы хотите, чтобы каждый поток, использующий класс A , имел собственное отдельное значение needsToBeThreadSafe , вам просто нужно украсить это поле атрибутом [ ThreadStatic ]. .

Дополнительные сведения см. В документации MSDN для ThreadStaticAttribute .

19
ответ дан 3 December 2019 в 00:48
поделиться

У вас есть два варианта: самый простой из представленных вами кодов - это ключевое слово 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 проще и отлично справится с этой задачей. Если это не так, вы можете использовать блокировку .

8
ответ дан 3 December 2019 в 00:48
поделиться
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
ответ дан 3 December 2019 в 00:48
поделиться

Похоже, вам нужен член Volatile .

static volatile int needsToBeThreadSafe = 0;
2
ответ дан 3 December 2019 в 00:48
поделиться

Вы также можете использовать 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();
    }
}
2
ответ дан 3 December 2019 в 00:48
поделиться

Для начала я согласен с ответами, используя lock () , это самый безопасный способ.

Но существует более минималистичный подход, в вашем примере кода отображается только один операторы, использующие needsToBeThreadSafe , и поскольку int является атомарным, вам нужно только предотвратить кеширование компилятором с использованием volatile:

class A
{
   static volatile int needsToBeThreadSafe = 0;

}

Но если вам нужно, чтобы needToBeThreadSafe было «ThreadSafe» по нескольким операторам, используйте замок.

2
ответ дан 3 December 2019 в 00:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: