2014-10-22 3 views
0

Мне нужно поменять карту std :: map, чтобы обновить некоторую конфигурацию. Это происходит в одном потоке.Как создать C++-карту :: swap thread safe?

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

В продюсерский потоке, я в настоящее время (псевдо-код):

pthread_mutex lock; 
std::map<int, char> current_config; 
std::map<int, char> new_config; 
... 
<Read into new config> 
ScopeLock(lock); 
current_config.swap(new_config); 

В потребительском потоке, я называю аксессор в продюсерском потоки, который выполняет следующие действия:

ScopeLock(lock) 
return current_config; 

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

Является ли эта нить безопасной?

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

+2

Ваш потребитель не делает никаких поисков. Похоже, что все, что он делает, возвращает ссылку или копию на карту, затем вызывающий выполняет поиск. Если это копия, то она неэффективна, но потокобезопасна. Если это ссылка, то она не является потокобезопасной (заблокированная блокировка освобождается при возврате, прежде чем вызываемый может выполнить поиск). – Adam

+0

Блокировка не защищает что-либо, если не все доступ туда проходит. Сожалею. – Surt

ответ

0

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

Если аксессуар возвращается по значению, то ваш код МОЖЕТ быть в безопасности, поскольку вы устанавливаете блокировку и возвращаете копию, а затем блокировку удаляете.

Я говорю «COULD», потому что ваша защита недостаточна: я полагаю, ваш продюсер не только заменяет карты, но также инициализирует, заполняет и обновляет их. Поэтому вам нужно будет установить блокировку для каждой функции производителя, которая каким-либо образом изменяет карту. Другой, который ваш потребитель мог прочитать карту, думая, что это безопасно, в то время как другие фрагменты кода изменяют существующие места.

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

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

+0

Так что я на самом деле решил сделать, это просто вставить конфигурацию и обновить мою карту в одном потоке и использовать флаг «версия». В моем потребительском потоке я собираюсь добавить простой механизм опроса, который будет читать в конфигурации и обновлять собственную копию карты только при обнаружении обновления. Это предотвратит проблему безопасности потоков. – Ryan0751