Общая схема синхронизации данных между потоками (помимо использования спин-блокировки) с атомарностью выглядит следующим образом:
int data;
std::atomic<bool> ready;
void thread1()
{
data = 123;
ready.store(true, std::memory_order_release);
}
void thread2()
{
while(!ready.load(std::memory_order_acquire));
int theData = data;
assert(theData == 123);
}
или лучше:
void thread2()
{
while(!ready.load(std::memory_order_relaxed));
std::atomic_thread_fence(std::memory_order_acquire);
int theData = data;
assert(theData == 123);
}
Флаг «готовности» используется для 1) определения того, когда данные действительно готовы, и 2) для отношения «случайный случай до».
Но если я каким-то образом знаю (потенциально не используя атомарность c ++), что данные будут готовы, когда я их прочитаю, то могу ли я опустить этот тип флага?
Могу ли я использовать это:
int data = 0;
void thread1()
{
sleep(1000);
data = 123;
std::atomic_thread_fence(some_order);
}
void thread2()
{
sleep(2000);
std::atomic_thread_fence(some_order);
int theData = data;
assert(theData == 123);
}
или
std::atomic<int> atmData(0);
void thread1()
{
sleep(1000);
atmData.store(123, some_order);
}
void thread2()
{
sleep(2000);
int theData = atmData.load(some_order);
assert(theData == 123);
}
А если так, то каким может быть some_order?
Я не уверен, что это было бы возможно, так как даже с std::memory_order_seq_cst
операции заказа все еще могут видеть устаревшее значение. С другой стороны, для работы std::atomic_thread_fence()
требуется атомарная операция (согласно https://en.cppreference.com/w/cpp/atomic/atomic_thread_fence).
РЕДАКТИРОВАТЬ: Это довольно теоретический вопрос о том, как синхронизация памяти работает в C ++, а не о том, как я должен использовать механизмы ожидания или знать, когда безопасно получить доступ к данным.