У меня есть код на работе, который запускает несколько потоков, которые выполняют некоторые операции, и если какой-либо из них не работает, они устанавливают общую переменную в false.Есть ли неявный барьер памяти с синхронизированным отношением на thread :: join?
Затем основной поток объединяет все рабочие потоки. Моделирование это выглядит примерно так (я закомментирована возможным исправление, которые я не знаю, если это необходимо):
#include <thread>
#include <atomic>
#include <vector>
#include <iostream>
#include <cassert>
using namespace std;
//atomic_bool success = true;
bool success = true;
int main()
{
vector<thread> v;
for (int i = 0; i < 10; ++i)
{
v.emplace_back([=]
{
if (i == 5 || i == 6)
{
//success.store(false, memory_order_release);
success = false;
}
});
}
for (auto& t : v)
t.join();
//assert(success.load(memory_order_acquire) == false);
assert(success == false);
cout << "Finished" << endl;
cin.get();
return 0;
}
Есть ли вероятность того, что основной поток будет читать переменный успех, как истинного даже если один из рабочих установил его на false?
Я обнаружил, что нити :: присоединиться() барьер полной памяти (source) но что подразумевает синхронизируется-с связи со следующим читают успеха переменных от основного потока, так что мы 'гарантированно получить самую новую ценность?
Является ли исправление, которое я разместил (в прокомментированном коде), необходимо в этом случае (или, может быть, другое исправление, если это неверно)?
Есть ли вероятность того, что читает успеха переменные будет оптимизированы прочь (поскольку это не летучее), и мы получим старое значение независимо от suppossed существовать барьер неявной памяти на нити :: присоединиться?
Код допускается работать с несколькими архитектурами (не помню всех из них, у меня нет makefile передо мной), но есть atleast x86, amd64, itanium, arm7.
Спасибо за любую помощь.
Редактировать: Я изменил пример, потому что в реальной ситуации более чем один поток может попытаться записать в успех переменной.
Не ясно ли об этом источник? «Поскольку создание и структура потока определяется как операция синхронизации, объединение потока обязательно происходит после завершения этого потока. Таким образом, вы увидите все, что обязательно произошло до прекращения потока». –
Я не уверен, так как вы можете увидеть здесь http: //en.cppreference.com/w/cpp/atomic/atomic_thread_fence ссылается только на синхронизацию между заборами и атомными объектами, ничего не происходит о синхронизации между ограждениями и обычными объектами. Я думаю, что объединение использует такой забор внутри, но я могу ошибаться. – Mikaka
[Да] (https://timsong-cpp.github.io/cppwp/thread.thread.member#4). В противном случае «join» будет бесполезным. –