Я тестировал это на Aarch64 на Qualcomm Snapdragon 835, с ARM64 GCC 9.3 и -О3 on.
preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: p> preptet: pre neppet: pre neppet: p> preptet: pre neppet: p> preptet: pre -spipt: pre -spipt: pre -spipt. class = "lang-cpp prettyprint-override">
Код: Выделить всё
std::atomic x;
std::atomic y;
int r1;
int r2;
void thread1_func() {
r1 = x.load(std::memory_order_relaxed);
if (r1) {
r2 = y.load(std::memory_order_relaxed);
}
}
void thread2_func() {
y.store(42, std::memory_order_relaxed);
x.store(1, std::memory_order_release);
}
void thread3_func() {
if (r2 == 0) {
return;
}
if (r1 == 0) {
printf("r2: %d\n", r2);
}
}
int main() {
while (1) {
// reset
x.store(0);
y.store(0);
r1 = 0;
r2 = 0;
std::thread t1(thread1_func);
std::thread t2(thread2_func);
std::thread t3(thread3_func);
t1.join();
t2.join();
t3.join();
}
return 0;
}
Неправильный забор < /h3>
Код: Выделить всё
void thread1_func() {
r1 = x.load(std::memory_order_acquire);
if (r1) {
r2 = y.load(std::memory_order_relaxed);
}
}
< /code>
или < /p>
void thread1_func() {
r1 = x.load(std::memory_order_relaxed);
if (r1) {
std::atomic_thread_fence(std::memory_order_acquire);
r2 = y.load(std::memory_order_relaxed);
}
}
< /code>
Но эти 2 примера не сработали! < /p>
'Правильный' Fence < /h3>
, пока я не попробую забор ниже: < /p>
void thread1_func() {
r1 = x.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (r1) {
r2 = y.load(std::memory_order_relaxed);
}
}
< /code>
На это время thread3_func < /code> никогда не войдет в ветвь печати. Atomic Код: Выделить всё
void thread1_func() {
r1.store(x.load(std::memory_order_acquire), std::memory_order_relaxed);
if (r1.load(std::memory_order_relaxed)) {
r2.store(y.load(std::memory_order_relaxed), std::memory_order_relaxed);
}
}
void thread2_func() {
y.store(42, std::memory_order_relaxed);
x.store(1, std::memory_order_release);
}
void thread3_func() {
if (r2.load(std::memory_order_relaxed) == 0) {
return;
}
if (r1.load(std::memory_order_relaxed) == 0) {
printf("r2: %d\n", r2.load(std::memory_order_relaxed));
}
}
void thread1_func() {
r1.store(x.load(std::memory_order_relaxed), std::memory_order_relaxed);
if (r1.load(std::memory_order_relaxed)) {
std::atomic_thread_fence(std::memory_order_acquire);
r2.store(y.load(std::memory_order_relaxed), std::memory_order_relaxed);
}
}
< /code>
И они оба никогда (5 000 000 итерально, кажется, достаточно, чтобы доказать это) введите ветвь печати, почему атомная версия примера 1,2 никогда не печатает, а неатомная версия делает? Их ASM выглядит ничем не по-меняему.>
Подробнее здесь: https://stackoverflow.com/questions/797 ... d-a-branch
Мобильная версия