Я играю с бесклассовым программированием C ++, и я придумал метод безопасного (?) Передача собственности на непревзойденную структуру данных (безопасная.std::unordered_map в моем тривиальном примере) из потока производителя в потребительский поток, используя только общую std :: atomic для синхронизации. Похоже, что это должно быть безопасным, но интуиция, как известно, ненадежна в программировании без блокировки, поэтому я ищу любые причины, почему этот подход может быть не безопасен на практике. итерации над содержимым возвращенного std :: unoromeded_map . Это может сделать это безопасно, потому что возвращаемый std :: unoromeded_map (_consumerThreadUpdatesTable) доступен только для потребительского потока; Поток производителя никогда не касается его._producerThreadUpdatesTable), а затем он может вызвать продюсерупюпдиатстоконсосуммер () , чтобы попытаться переместить содержимое своей частной таблицы в таблицу общего доступа (_bridgeUpdatesTable). Поток продюсера также вызывает продюсерпсупдиатстоконсосуммер () периодически, на случай, если предыдущий вызов не смог успешно продвинуть обновления. std :: atomic . Если эта переменная верна, то только только потребительский поток может получить доступ к _bridgeupdateStable , или если эта переменная является ложной, то только поток производителя может получить доступ к _bridgeupdatable .
Причина (я думаю), что это должно быть потоком, что каждая нить будет только относиться к _bridgeupdate-stempate-stemptable
#include
#include
// This object lets us safely transport sets of key-value pair updates from a single ProducerThread to a single ConsumerThread without requiring any Mutex locking
class KeyedParameterBridge
{
public:
KeyedParameterBridge() : _consumerOwnsBridgeUpdatesTable(false)
{
// empty
}
/** Called by the producer thread; places a pending update into the producer-thread's local pending-update-table. */
void ProducerPutUpdate(int parameterID, float parameterValue) {_producerThreadUpdatesTable[parameterID] = parameterValue;}
/** Called by the producer thread; attempts to push all of the updates currently placed (via ProducerPutUpdate()) to
* the _bridgeUpdatesTable where the consumer thread will be able to access them
* @returns true if we were able to push some updates in this call, or false if didn't push any updates
*/
bool ProducerPushUpdatesToConsumer()
{
if (_producerThreadUpdatesTable.size() == 0) return false; // no updates to push
if (_consumerOwnsBridgeUpdatesTable.load()) return false; // can't safely do anything yet; we'll have to wait until the ConsumerThread consumes _bridgeUpdatesTable's current contents
_bridgeUpdatesTable = std::move(_producerThreadUpdatesTable); // O(1) pointer-move from _producerThreadUpdatesTable to _bridgeUpdatesTable
_consumerOwnsBridgeUpdatesTable = true; // so the ConsumerThread will know the _bridgeUpdatesTable is safe for him to access now
_producerThreadUpdatesTable.clear(); // make sure our producer-side table is in a known-empty state
return true;
}
/** Called periodically by the consumer thread; returns any available updates for the consumer thread to apply to its local data structure */
const std::unordered_map & ConsumerConsumeUpdates()
{
_consumerThreadUpdatesTable.clear(); // make sure our consumer-side table is in a known-empty state
if (_consumerOwnsBridgeUpdatesTable.load()) // see if we have access
{
_consumerThreadUpdatesTable = std::move(_bridgeUpdatesTable); // O(1) pointer-move from _bridgeUpdatesTable to _consumerThreadUpdatesTable
_consumerOwnsBridgeUpdatesTable = false; // so the ProducerThread will know we already grabbed the update and he can push again now
}
return _consumerThreadUpdatesTable;
}
private:
std::atomic _consumerOwnsBridgeUpdatesTable; // true iff the _bridgeUpdatesTable currently contains data for the consumer thread to consume
std::unordered_map _producerThreadUpdatesTable; // populated by the producer-thread, never accessed by the consumer thread
std::unordered_map _bridgeUpdatesTable; // access to this table is governed by the state of (_consumerOwnsBridgeUpdatesTable)
std::unordered_map _consumerThreadUpdatesTable; // read by the consumer-thread, never accessed by the producer thread
};
Подробнее здесь: https://stackoverflow.com/questions/797 ... -structure
Независимо от того, можно ли использовать STD :: Atomic для контроля доступа к структуре данных таким образом? ⇐ C++
Программы на C++. Форум разработчиков
1758325077
Anonymous
Я играю с бесклассовым программированием C ++, и я придумал метод безопасного (?) Передача собственности на непревзойденную структуру данных (безопасная.std::unordered_map в моем тривиальном примере) из потока производителя в потребительский поток, используя только общую std :: atomic для синхронизации. Похоже, что это должно быть безопасным, но интуиция, как известно, ненадежна в программировании без блокировки, поэтому я ищу любые причины, почему этот подход может быть не безопасен на практике. итерации над содержимым возвращенного std :: unoromeded_map . Это может сделать это безопасно, потому что возвращаемый std :: unoromeded_map (_consumerThreadUpdatesTable) доступен только для потребительского потока; Поток производителя никогда не касается его._producerThreadUpdatesTable), а затем он может вызвать продюсерупюпдиатстоконсосуммер () , чтобы попытаться переместить содержимое своей частной таблицы в таблицу общего доступа (_bridgeUpdatesTable). Поток продюсера также вызывает продюсерпсупдиатстоконсосуммер () периодически, на случай, если предыдущий вызов не смог успешно продвинуть обновления. std :: atomic . Если эта переменная верна, то только только потребительский поток может получить доступ к _bridgeupdateStable , или если эта переменная является ложной, то только поток производителя может получить доступ к _bridgeupdatable .
Причина (я думаю), что это должно быть потоком, что каждая нить будет только относиться к _bridgeupdate-stempate-stemptable
#include
#include
// This object lets us safely transport sets of key-value pair updates from a single ProducerThread to a single ConsumerThread without requiring any Mutex locking
class KeyedParameterBridge
{
public:
KeyedParameterBridge() : _consumerOwnsBridgeUpdatesTable(false)
{
// empty
}
/** Called by the producer thread; places a pending update into the producer-thread's local pending-update-table. */
void ProducerPutUpdate(int parameterID, float parameterValue) {_producerThreadUpdatesTable[parameterID] = parameterValue;}
/** Called by the producer thread; attempts to push all of the updates currently placed (via ProducerPutUpdate()) to
* the _bridgeUpdatesTable where the consumer thread will be able to access them
* @returns true if we were able to push some updates in this call, or false if didn't push any updates
*/
bool ProducerPushUpdatesToConsumer()
{
if (_producerThreadUpdatesTable.size() == 0) return false; // no updates to push
if (_consumerOwnsBridgeUpdatesTable.load()) return false; // can't safely do anything yet; we'll have to wait until the ConsumerThread consumes _bridgeUpdatesTable's current contents
_bridgeUpdatesTable = std::move(_producerThreadUpdatesTable); // O(1) pointer-move from _producerThreadUpdatesTable to _bridgeUpdatesTable
_consumerOwnsBridgeUpdatesTable = true; // so the ConsumerThread will know the _bridgeUpdatesTable is safe for him to access now
_producerThreadUpdatesTable.clear(); // make sure our producer-side table is in a known-empty state
return true;
}
/** Called periodically by the consumer thread; returns any available updates for the consumer thread to apply to its local data structure */
const std::unordered_map & ConsumerConsumeUpdates()
{
_consumerThreadUpdatesTable.clear(); // make sure our consumer-side table is in a known-empty state
if (_consumerOwnsBridgeUpdatesTable.load()) // see if we have access
{
_consumerThreadUpdatesTable = std::move(_bridgeUpdatesTable); // O(1) pointer-move from _bridgeUpdatesTable to _consumerThreadUpdatesTable
_consumerOwnsBridgeUpdatesTable = false; // so the ProducerThread will know we already grabbed the update and he can push again now
}
return _consumerThreadUpdatesTable;
}
private:
std::atomic _consumerOwnsBridgeUpdatesTable; // true iff the _bridgeUpdatesTable currently contains data for the consumer thread to consume
std::unordered_map _producerThreadUpdatesTable; // populated by the producer-thread, never accessed by the consumer thread
std::unordered_map _bridgeUpdatesTable; // access to this table is governed by the state of (_consumerOwnsBridgeUpdatesTable)
std::unordered_map _consumerThreadUpdatesTable; // read by the consumer-thread, never accessed by the producer thread
};
Подробнее здесь: [url]https://stackoverflow.com/questions/79770024/is-it-thread-safe-to-use-stdatomicbool-to-control-access-to-a-data-structure[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия