Обеспечивают ли std::promise::set_value() и std::future::wait() защиту памяти?

#c #c 11

#c #c 11 #параллелизм

Вопрос:

Если я сделаю следующее:

 std::promise<void> p;
int a = 1;

std::thread t([amp;] {
  a = 2;
  p.set_value();
});

p.get_future().wait();

// Is the value of `a` guaranteed to be 2 here?
 

cppreference может сказать об этом set_value() , но я не уверен, что это значит:

Вызовы этой функции не приводят к гонкам данных с вызовами get_future (но они не должны синхронизироваться друг с другом).

Выполните set_value() и wait() обеспечьте синхронизацию получения / выпуска (или какую-либо другую форму)?

Ответ №1:

Из моего чтения, я полагаю a , гарантировано, что в конце будет 2. Обратите внимание на информацию о самом обещании (курсив мой):

Обещание — это «нажимной» конец канала связи promise-future: операция, которая сохраняет значение в общем состоянии, синхронизируется с (как определено в std ::memory_order ) успешным возвратом из любой функции, ожидающей общего состояния (например, std::future::получить).В противном случае одновременный доступ к одному и тому же общему состоянию может конфликтовать: например, несколько вызывающих std::shared_future::get должны быть либо доступны только для чтения, либо обеспечивать внешнюю синхронизацию.

Конечно, я рекомендую вам прочитать, что означает, что что-то синхронизируется. Для этой ситуации это означает, что set_value это рассматривается как происходящее между потоками — до и, следовательно, из того, что я получаю, запись a является видимым побочным эффектом. Вы можете найти больше здесь.

Что означает ваш вопрос get_future ? Это просто означает, что вы можете безопасно вызывать get_future и set_value из разных потоков, и это ничего не сломает. Но также это не обязательно само по себе создает какие-либо ограничения памяти. Единственными точками синхронизации, которые являются надежными и безопасными, являются set_value from std::promise и get from std::future .