Многоуровневая блокировка? - PullRequest
0 голосов
/ 16 ноября 2018

Играя с параллельной обработкой, у меня есть цикл Parallel.For, который выполняет поиск по перечисляемому, и, если он не находит то, что ищет, добавляет его.Я продолжаю сталкиваться с проблемами, когда один поток изменяет перечисляемое, в то время как другой поток выполняет поиск, что вызывает исключение.Очевидное решение - использовать lock как для поиска, так и для входа, но это немного грубая сила.Мне бы хотелось, чтобы он мог запускать несколько одновременных поисков, поэтому я не хочу полностью блокировать его, пока один поток выполняет поиск, но я хочу запретить ему выполнять добавление во время поиска.Есть ли способ сделать двухуровневую блокировку таким образом?

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Возможно, вы захотите использовать ReaderWriterLock .

private ReaderWriterLockSlim lock = new ReaderWriterLockSlim();

public string Read () {
    lock.EnterReadLock ();
    try {
        return "xxx";
    } finally {
        lock.ExitReadLock();
    }
}

public void Write () {
    lock.EnterWriteLock ();
    try {
        // ...
    } finally {
        lock.ExiteWriteLock ();
    }
}

Несколько потоков могут владеть частью «читателя» ReaderWriterLock, но только одна может владеть частью «писателя» (и не может быть читателя, пока есть писатель).

0 голосов
/ 16 ноября 2018

Я бы подумал об использовании какой-либо формы неизменяемой коллекции и Interlocked для замены общего экземпляра.

Например, вы упомянули "Looks ups", как и ImmutableDictionaryбыть хорошим совпадением?

Тогда для поиска и обновления у вас есть что-то вроде:

var local = sharedReference;
while(!local.ContainsKey(lookupValue))
{
    var newValue = /* Whatever */
    var newLocal = local.Add(lookupValue,newValue);
    var result = Interlocked.CompareExchange(ref sharedReference, newLocal, local);
    if(result == local) break;
    local = result;
}
//At this point, local definitely contains a key for lookupValue
...