С# Interlocked работает как механизм блокировки?

Пока я читал о ReaderWriterLockSlim механизме блокировки, был один парень, который предположил, что Interlock функции можно использовать для более тонкой блокировки

Кроме того, я нашел здесь еще один ответ от Марка:

... Записи вносят свои изменения в клонированную копию, а затем используют Interlocked.CompareExchange для замены ссылки (повторно применяя свои изменения, если другой поток изменил ссылку в промежутке).

Ну, в настоящее время все, что я знаю об объекте Interlocked, это то, что он используется (в многопоточной среде) для выполнения атомарных операций additions, compare, compareExchange. (и я знаю, как им пользоваться)

Но (и вот мой вопрос) —

Вопрос

Как я могу использовать его как замок? (пример кода будет высоко оценен)

редактировать

Для простоты я вставляю этот код (который не является потокобезопасным — если бы Go вызывался двумя потоками одновременно, можно было бы получить ошибку деления на ноль):

class ThreadUnsafe
 {
   static int _val1 = 1, _val2 = 1;

   static void Go()
       {
        if (_val2 != 0) Console.WriteLine (_val1 / _val2);
        _val2 = 0;
       }
}

Как я могу использовать Interlock для замены замка (что решило бы проблему)?


person Royi Namir    schedule 24.05.2014    source источник
comment
Как я могу использовать его в качестве замка? - с помощью lock(){}.   -  person Henk Holterman    schedule 24.05.2014


Ответы (2)


Interlocked используется для реализации алгоритмов без блокировки и структур данных. Следовательно, это не «более тонкая блокировка» и даже не блокировка вообще. Он позволяет безопасно выполнять небольшие и четко определенные операции в многопоточной среде: например, если вы хотите, чтобы два потока увеличивали одну и ту же переменную, вы можете использовать Interlocked для этого вместо получения тяжеловесная блокировка и использование «обычного приращения».

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

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

class InterlockedLock
{
    private int locked;

    public void Lock()
    {
        while (Interlocked.CompareExchange(ref locked, 1, 0) != 0)
            continue; // spin
    }

    public void Unlock()
    {
        locked = 0;
    }
}

В этом примере locked изначально равно нулю. Когда поток пытается получить его в первый раз, locked становится равным 1, а последующие потоки, пытающиеся получить Lock, будут вращаться до тех пор, пока кто-нибудь не вызовет Unlock, чтобы снова сделать locked 0.

person zneak    schedule 24.05.2014
comment
Вы хотите, чтобы volatile гарантировал, что запись в locked не будет переупорядочена, чтобы закончиться перед любой записью в критической секции. - person Trillian; 24.05.2014

Блокировка с помощью Interlocked выполняется путем замены нового значения старым значением только в том случае, если старое значение не изменилось. Если это так, мы пытаемся снова, пока это не произойдет (вращение).

Это можно использовать для замены мелкозернистых блокировок, которые обновляют только одно значение, или для реализации облегченного механизма блокировки, такого как SpinLock.

Пример:

private int _value;

int oldValue;
int originalValue;
do
{
    oldValue = _value;
    originalValue = Interlocked.CompareExchange(ref _value, newValue, oldValue);
}
while (originalValue != oldValue);

Вместо:

lock(_lock)
{
    _value = newValue;
}
person i3arnon    schedule 24.05.2014