即使对于一个简单的双线程通信示例,我也难以用C11原子和memory_fence样式来表达它以获得正确的内存排序:
共享数据:
volatile int flag, bucket;
Run Code Online (Sandbox Code Playgroud)
生产者线程:
while (true) {
int value = producer_work();
while (atomic_load_explicit(&flag, memory_order_acquire))
; // busy wait
bucket = value;
atomic_store_explicit(&flag, 1, memory_order_release);
}
Run Code Online (Sandbox Code Playgroud)
消费者线程:
while (true) {
while (!atomic_load_explicit(&flag, memory_order_acquire))
; // busy wait
int data = bucket;
atomic_thread_fence(/* memory_order ??? */);
atomic_store_explicit(&flag, 0, memory_order_release);
consumer_work(data);
}
Run Code Online (Sandbox Code Playgroud)
据我所知,上面的代码可以正确地命令存储在桶中 - > flag-store - > flag-load - > load-from-bucket.但是,我认为在load-from-bucket和使用新数据重新写入桶之间仍存在竞争条件.要在读取桶之后强制执行订单,我想我需要atomic_thread_fence()在读取桶和以下atomic_store之间进行显式操作.不幸的是,似乎没有任何memory_order论据可以对前面的负载强制执行任何操作,甚至没有memory_order_seq_cst.
一个非常脏的解决方案可能是bucket在消费者线程中使用虚拟值重新分配:这与消费者只读概念相矛盾.
在较旧的C99/GCC世界中,我可以使用__sync_synchronize()我认为足够强大的传统.
什么是更好的C11风格的解决方案来同步这种所谓的反依赖?
(当然我知道我应该更好地避免这种低级编码并使用可用的更高级别的结构,但我想了解...)