C # заблокирован функционирует как механизм блокировки?

1

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

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

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

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

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

Вопрос

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

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

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

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

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

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

Теги:
multithreading
locking
interlocked

2 ответа

5
Лучший ответ

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.

  • 0
    Также изменчив для других потоков, чтобы увидеть немедленное изменение
  • 1
    Вы хотите, чтобы volatile гарантировало, что запись в locked не будет переупорядочена и завершится раньше, чем какая-либо запись в критическом разделе.
0

Блокировка с 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;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню