доступ потока к используемым переменным - PullRequest
1 голос
/ 31 октября 2010

Мне было интересно, если у меня многоядерный процессор и несколько потоков, возможно ли, что программа завершится сбоем, если 2 или более потоков одновременно получат доступ к переменной?Как я могу временно заблокировать переменную, чтобы одновременно был ограничен доступ?

С уважением, Александру Бадеску

Ответы [ 4 ]

5 голосов
/ 31 октября 2010

Это не сбой , но это может дать неправильные результаты.

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

private readonly object monitor = new object();
private int sharedVariable;

public void MethodThatSetsVariable()
{
    lock (monitor)
    {
        sharedVariable = 5;
    }
}

public void MethodThatReadsVariable()
{
    int foo;
    lock (monitor)
    {
        foo = sharedVariable;
    }
    // Use foo now
}

Альтернативы:

  • Используйте переменную volatile, хотя точное поведение volatile трудно понять.(Ну, в любом случае, это вне меня.)
  • Используйте методы класса Interlocked

Обратите внимание, что оба они лучше всего подходят, когда вы используете только одну общую переменную 'Вы заинтересованы в этом. Когда вам нужно получить доступ к набору переменных и убедиться, что вы видите только полностью согласованное состояние, блокировки - это самый простой способ.

Другой вариант - и предпочтительнее, если это вообще возможно.- в первую очередь избегать необходимости изменяемого общего состояния.Это не всегда возможно, по крайней мере, без полной модернизации архитектуры передачи сообщений - но это стоит того, чтобы по возможности.Неизменяемые типы могут помочь в достижении этой цели.

2 голосов
/ 31 октября 2010

Вы можете использовать ключевое слово lock или Interlocked класс.

, например

public class Foo
{
   private object barLock = new object();
   private int bar;

   public void Add(int x)
   {
        lock (barLock)
        {
            this.bar += x;
        }
   }
}

или

public class Foo
{
   private int bar;

   public void Increment()
   {
        Interlocked.Increment(ref x);
   }
}

Я бы использовал класс Interlocked всякий раз, когда это возможно, поскольку это, как правило, самый простой и эффективный (самый быстрый) способ сделать это, но обслуживаются только определенные операции. Для более сложных операций lock - это путь.

Я бы не рекомендовал использовать ключевое слово C # volatile, так как это влияет на all доступ к данному полю. Лучше придерживаться понятий более высокого уровня, таких как lock или Interlocked.

2 голосов
/ 31 октября 2010

возможно, что программа потерпит крах, если 2 или более потоков одновременно получат доступ к переменной

Вряд ли программа вылетит. Вероятно, он не будет вести себя так, как вы ожидаете, поскольку это создаст условия гонки.

Как временно заблокировать переменную, чтобы ограничить одновременный доступ к нескольким файлам

Использование оператора блокировки .

1 голос
/ 31 октября 2010

с использованием оператора lock (который действительно является синтаксическим сахаром для Monitor.Enter / Exit)

...