Параллельный контейнер - синхронизировать при стирании элемента - PullRequest
1 голос
/ 17 ноября 2011

Я успешно использую Concurrency::concurrent_unordered_map в своей программе (это реализация, сделанная Microsoft).Это необходимо, потому что несколько вставок / обновлений для элементов и довольно редкие удаления выполняются одновременно.

Я знаю, что этот контейнер (как и все другие одновременные контейнеры) предоставляет небезопасный метод erase() - для удаленияузел.

Какой, по вашему мнению, лучший способ сделать процесс стирания также безопасным для потоков?Это случается редко, как я уже сказал (только потому, что вмешательство пользователя), и мне бы не хотелось, чтобы критический раздел вводился каждый раз, когда я выполняю поиск в контейнере (или в этом отношении любые другие операции, такие как итератор).обход и обновление узла).Как вы думаете?Я также думал о механизме, основанном на событиях, но я не понимаю, как это применимо здесь.

Ответы [ 3 ]

2 голосов
/ 18 ноября 2011

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

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

    InsertOperation(key) -- this inserts the key in case is not present (and constructs a default constructed value)
    {
       reader_writer_lock::scoped_lock_read guard(reader_writer_lock);
       ...
    }

    value Find(key)
    {
        reader_writer_lock::scoped_lock_read guard(reader_writer_lock);
        ...
     }

     void EraseElement(key)
     {
        reader_writer_lock::**scoped_lock** guard(reader_writer_lock);
        ...
     }
0 голосов
/ 18 ноября 2011

И еще одна статья на тему параллельных структур данных: Структуры данных без блокировки с указателями опасности от Андрея Александреску и Магеда Михаила

0 голосов
/ 18 ноября 2011

Другим решением, которое должно работать вполне нормально, я думаю, будет запуск события при вводе EraseElement(key) и сброс по окончании процедуры. Таким образом, любая другая операция должна ждать этого события, прежде чем продолжить. Я думаю, что это, вероятно, обеспечит тот же уровень производительности, что и мое предыдущее решение.

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