为什么没有锁定的单生产者单用户循环队列线程是安全的?

11 algorithm thread-safety data-structures

这似乎是真的,但我的想法一直很混乱.有人可以给出一个明确的解释和一些关键的案例,它总是在没有锁定的情况下运作 谢谢!

Bor*_*jev 6

这肯定取决于循环队列的实现。但是,如果正如我想象的那样,您有两个索引 -队列的head和。tail生产者与 一起工作tail,消费者与 一起工作head。它们共享消息数组,但使用两个不同的指针。

生产者和消费者可能遇到冲突的唯一情况是消费者检查新消息并且该消息在检查后立即到达。但在这种情况下,消费者会稍等一下并再次检查。程序的正确性不会丢失。

之所以能在单生产者单消费者下工作正常,主要是因为两个用户不共享太多内存。如果有多个生产者,例如,您将有多个线程访问,head并且可能会出现冲突。

编辑dasblinkenlight 在他的评论中提到,只有当两个线程递增/递减各自的计数器作为其消费/生产的最后一个操作时,我的推理才成立。

  • +1您应该提到,线程安全性取决于生产者首先将项目写入队列,然后才递增“tail”索引。在单线程环境中,顺序并不重要,但在并发环境中,切换顺序会破坏事情。 (4认同)

Kos*_*tas 5

单个生产者-单个消费者循环队列背后的真正窍门是原子地修改了头和尾指针。这意味着,如果内存中的位置从值A更改为值B,则在值更改时读取内存的观察者(即读取器)将得到A或B的结果,而没有其他结果。

因此,例如,如果您使用的是16位指针,但您要以两个8位的步长来更改它们,则队列将无法工作(这可能会发生,具体取决于您的CPU体系结构和内存对齐要求)。在这种情况下,读取器可能会读取完全错误的瞬态值。

因此,请确保在您的平台上原子地修改了指针!