При каких условиях может произойти сбой TryDequeue и аналогичных методов сбора System.Collections.Concurrent - PullRequest
11 голосов
/ 13 апреля 2011

Я недавно заметил, что внутри объектов коллекции, содержащихся в System.Collections.Concurrent пространстве имен, обычно можно увидеть Collection.TrySomeAction() вместо Collection.SomeAction().

В чем причина этого?Я полагаю, это как-то связано с блокировкой?

Поэтому мне интересно, при каких условиях попытка (например) вывести элемент из стека, очереди, сумки и т. Д. Не удалась?

Ответы [ 3 ]

10 голосов
/ 13 апреля 2011

Коллекции в пространстве имен System.Collections.Concurrent считаются поточно-ориентированными, поэтому их можно использовать для написания многопоточных программ, которые обмениваются данными между потоками.

До .NET 4 вам приходилосьпредоставьте свои собственные механизмы синхронизации, если несколько потоков могут обращаться к одной общей коллекции.Вы должны были заблокировать коллекцию каждый раз, когда вы изменяли ее элементы.Вам также может понадобиться заблокировать коллекцию каждый раз, когда вы обращаетесь к ней (или перечисляете).Это для простейших многопоточных сценариев.Некоторые приложения создают фоновые потоки, которые со временем доставляют результаты в общую коллекцию.Другой поток будет читать и обрабатывать эти результаты.Вам нужно было реализовать собственную схему передачи сообщений между потоками, чтобы уведомлять друг друга о появлении новых результатов и использовании этих новых результатов.Классы и интерфейсы в System.Collections.Concurrent обеспечивают согласованную реализацию для тех и других распространенных проблем многопоточного программирования, связанных с общими данными между потоками, без блокировок .

Try<something> имеет семантику - попробуйте выполнить это действие и вернуть результат операции.DoThat семантика обычно использует исключительную механику, чтобы указать на ошибку, которая может быть неэффективной.В качестве примеров они могут возвращать false,

  • , если вы попытаетесь добавить новый элемент, вы можете уже иметь его в ConcurentDictionary;
  • если вы попытаетесь получить элемент из коллекции, он может не существует там;
  • если вы попытаетесь обновить элемент, то можетебыть более новым элементом, поэтому метод гарантирует, что он обновляет только тот элемент, который намеревался обновить.

Попробуйте прочитать:

9 голосов
/ 13 апреля 2011

Что вы имеете в виду под fail ?

Возьмите следующий пример:

var queue = new Queue<string>();
string temp = queue.Dequeue();
// do something with temp

Приведенный выше код сгенерирует исключение, так как мы пытаемся удалить изпустая очередь.Теперь, если вместо этого вы используете ConcurrentQueue<T>:

var queue = new ConcurrentQueue<string>();
string temp;
if (queue.TryDequeue(out temp))
{
    // do something with temp
}

Приведенный выше код не сгенерирует исключение.Очередь по-прежнему не сможет удалить элемент из очереди, но код не будет сгенерирован при выдаче исключения.Реальное использование этого становится очевидным в многопоточной среде.Код для несовместимого Queue<T> обычно будет выглядеть примерно так:

lock (queueLock)
{
    if (queue.Count > 0)
    {
        string temp = queue.Dequeue();
        // do something with temp   
    } 
}

Чтобы избежать условий гонки, нам нужно использовать блокировку, чтобы гарантировать, что с очередью ничего не произойдет во время, когдапроходит проверку Count, звоните DequeueConcurrentQueue<T> нам не нужно проверять Count, но вместо этого мы можем вызвать TryDequeue.

Если вы изучите типы, найденные в пространстве имен Systems.Collections.Concurrent, вы обнаружите, что многие из нихобернуть две операции, которые обычно вызываются последовательно, и для которых традиционно требуется блокировка (Count с последующим Dequeue в ConcurrentQueue<T>, GetOrAdd в ConcurrentDictionary<TKey, TValue> заменяет последовательности вызова ContainsKey, добавление элемента и получение егои т. д.).

0 голосов
/ 13 апреля 2011

Если нечего «убрать из очереди», например ... Этот "Try-Pattern" обычно используется во всех элементах FCL и BCL. Это не имеет ничего общего с блокировкой, одновременные коллекции (или, по крайней мере, должны) реализованы в основном без блокировок ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...