В приведенном ниже коде показаны два способа получения общего состояния через атомный флаг. Поток читателя вызывает poll1()
или poll2()
, чтобы проверить, сигнализировал ли он флаг.Преимущества и недостатки как-то условного std :: atomic_thread_fence приобретают?
Опрос Вариант № 1:
bool poll1() {
return (flag.load(std::memory_order_acquire) == 1);
}
Опрос Вариант № 2:
bool poll2() {
int snapshot = flag.load(std::memory_order_relaxed);
if (snapshot == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
return true;
}
return false;
}
Обратите внимание, что вариант # 1 был presented in an earlier question, и вариант # 2 похож на example code at cppreference.com.
Предполагая, что читатель согласится только исследовать общее состояние, если функция возвращает poll
true
, является две poll
функции как правильно и эквивалент?
Есть ли у варианта № 2 стандартное название?
Каковы преимущества и недостатки каждого варианта?
Возможно ли, что вариант № 2 будет более эффективным на практике? Возможно ли, чтобы он был менее эффективным?
Вот полный рабочий пример:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
int x; // regular variable, could be a complex data structure
std::atomic<int> flag { 0 };
void writer_thread() {
x = 42;
// release value x to reader thread
flag.store(1, std::memory_order_release);
}
bool poll1() {
return (flag.load(std::memory_order_acquire) == 1);
}
bool poll2() {
int snapshot = flag.load(std::memory_order_relaxed);
if (snapshot == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
return true;
}
return false;
}
int main() {
x = 0;
std::thread t(writer_thread);
// "reader thread" ...
// sleep-wait is just for the test.
// production code calls poll() at specific points
while (!poll2()) // poll1() or poll2() here
std::this_thread::sleep_for(std::chrono::milliseconds(50));
std::cout << x << std::endl;
t.join();
}
Вариант 2 выглядит ужасно, как «двойная проверка блокировки антишаблона», и если вы используете его, я хотел бы видеть много комментариев объясняя, почему это не так (вероятно, со ссылкой здесь). Какая разница в производительности делает poll2? ('cos если ответ «не так много», я бы придерживался poll1 по принципу KISS). –
Они выглядят более или менее одинаково для меня. Я повторю чувства Мартина Боннера, а также добавлю, что если вы заинтересованы в эффективности, то проще всего сделать это, чтобы профиль! – AndyG
@MartinBonner ваши проблемы более или менее соответствуют мотивации для вопроса. Боковое примечание: дважды проверенная блокировка была только анти-шаблоном до C++ 11: http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/ –