У меня есть несколько предварительно обработанных серверных процессов, которые принимают запросы на изменение общего списка STL C ++ на сервере. Каждый процесс просто помещает новый элемент в конец списка и возвращает итератор.
Я не уверен, как каждый процесс должен пытаться получить блокировку в списке? Должно ли оно быть на всем объекте или списки STL способны обрабатывать параллелизм, поскольку мы просто помещаем элемент в конец списка?
Механизм такой синхронизации между несколькими процессами требует от разработчика решения нескольких проблем. Во-первых, все, что распределяется между процессами, должно быть установлено вне их. На практике это обычно означает использование shared memory
,
Затем эти процессы должны взаимодействовать друг с другом в отношении доступа к разделяемой памяти. В конце концов, если один поток начинает работать с разделяемой структурой данных, но выгружается перед завершением операции, он оставляет данные несогласованными.
Эта синхронизация может быть выполнена с использованием конструкций операционной системы, таких как семафоры в linux, и позволит конкурировать конкурирующим процессам.
Увидеть Это для Linux на основе IPC подробно
Увидеть Это для Windows IPC подробно
Для справки вы можете использовать Boost.Interprocess
документация которая обеспечивает независимую от платформы реализацию механизмов IPC.
Предполагая, что вы имели в виду потоки скорее, чем процессы вы можете поделиться контейнерами STL, но вы должны быть осторожны в отношении синхронизации. Контейнеры STL в некоторой степени безопасны для потоков, но вам необходимо понимать гарантии безопасности потоков, данные:
Причина этих ограничений заключается в том, что интерфейс для контейнеров ориентирован на эффективное использование в одном потоке, и вы не хотите препятствовать обработке неразделенного контейнера с возможностью совместного использования между потоками. Кроме того, интерфейс контейнера не подходит для какого-либо механизма параллелизма, поддерживаемого контейнером. Например, только потому, что v.empty()
только вернулся false
это не значит что v.pop()
работает, потому что контейнер уже может быть пустым: если бы была внутренняя синхронизация, любая блокировка была бы снята один раз empty()
возвращается, и контейнер может быть изменен ко времени pop()
называется.
Относительно легко создать очередь, которая будет использоваться для связи между различными потоками. Было бы использовать std::mutex
и подходящее воплощение std::condition_variable
, Я думаю, что есть что-то вроде этого, предложенное для включения в стандарт, но оно пока не является частью стандартной библиотеки C ++. Обратите внимание, однако, что такой класс будет не верните итератор во вставленный элемент, потому что к тому времени, когда вы получите к нему доступ, элемент может снова исчезнуть, и было бы сомнительно, для чего в любом случае используется итератор.
Контейнеры стандартной библиотеки не обеспечивают автоматической защиты от одновременных изменений, поэтому вам необходима глобальная блокировка для каждого доступа к очереди.
Вы даже должны быть осторожны с итераторами или ссылками на элементы списка, поскольку вы не обязательно знаете, когда соответствующий элемент был удален из списка.