我有两个共享循环队列的线程。队列的内容是无符号数字(x86_64上为unsigned long
)。一个线程是生产者和另一个消费者。如果队列中元素的值为0且生成器始终生成非零值,则生成器仅写入队列的元素,而消费者仅在其值为非零时才使用它。消费者每当消费它时,也会将元素重置为0,这样生产者就可以知道消费者已经消耗了它。
现在我认为,由于采用这种方案,队列中存在严格的元素访问顺序,我们不需要使用同步或原子变量。我的假设是否正确?或者我在这里缺少一些东西?请记住,x86_64具有相对严格的一致性内存模型,并且只能在商店之前放置不相关的负载。它还具有缓存一致性,可主动更新缓存。我还使用volatile
变量来确保编译器不会缓存它们。
答案 0 :(得分:3)
是的,您需要同步,因为如果消费者已经赶上了生产者,那么生产者和消费者可能会同时尝试从同一位置读取和/或写入反之亦然
即使您的处理器对您正在使用的数据类型执行原子操作,您通常也需要显式请求原子操作(通过适当的API)以获得适当的内存屏障并确保一致性,即使您的线程在不同的内核上运行
答案 1 :(得分:2)
我认为你不需要同步或原子变量。
两个线程一个生产者和一个消费者不会与写同一个条目冲突。
因为如果循环队列实现正确(例如,一个读取头变量,一个写入标记变量),则两个线程不能在同一位置上操作。没有必要限制进入结构。
阅读后似乎无需重置输入。因为您应该移动读取头,生成器线程可以通过比较读取头变量和写入标记变量来知道可以写入一个条目。
可能对你有帮助:)
答案 2 :(得分:0)
如果生产者和消费者只访问一个变量,那么您似乎不需要同步。但既然你说你使用循环缓冲区,你使用索引。如果不同步,索引变量很容易受到攻击。