многопоточная синхронизация c ++ с изменяющимся количеством ресурсов - PullRequest
0 голосов
/ 06 июля 2018

У меня возникли проблемы с поиском способа синхронизации потоков, когда количество ресурсов неизвестно / изменяется. Проблема:

Существует массив ресурсов R, который совместно используется несколькими потоками, и каждый поток может выполнить одно из 3 действий:

  1. создать и добавить новый ресурс в массив (увеличив таким образом его размер).

  2. удалить ресурс из массива (уменьшив его размер).

  3. доступ к ресурсу (запись / чтение его значения).

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

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

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

Мне бы хотелось услышать идеи о том, как справиться с такой проблемой. спасибо.

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

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

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

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

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

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

если вы не хотите, чтобы поток ожидал добавления ресурса, но ваша проблема только в том, что вывод «ошибка не существует» неверна, когда ресурс присутствует в тот момент, когда пользователь получает ошибку, ответ: « нет проблем!". ресурс не существовал в тот момент, когда мы проверяли его, и сообщалось об ошибке.

Обновление:

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

0 голосов
/ 06 июля 2018

Это стандартная проблема синхронизации, просто управляйте доступом к std :: vector, содержащему ваши ресурсы, с помощью std :: mutex (или std :: shared_mutex, если доступно и уместно). Ничто не может захватить новую блокировку ресурса, пока вы не освободите общий мьютекс для вектора, если вы все сделаете правильно.

...