这种Python producerconsumer无锁方法是线程安全的吗?

2024-05-11 22:42:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近编写了一个程序,它使用了一个简单的生产者/消费者模式。一开始使用不当穿线。锁定我最终修复了。但它让我思考是否有可能以无锁的方式实现生产者/消费者模式。在

我的要求很简单:

  • 一条生产线。在
  • 一条消费者线索。在
  • 队列只能容纳一个项目。在
  • 生产商可以在当前产品被消耗之前生产下一个产品。现在的物品因此丢失了,但我没问题。在
  • 消费者可以在生产下一个商品之前消费当前商品。因此,当前项被消费两次(或更多),但这对我来说没问题。在

所以我写了这个:

QUEUE_ITEM = None

# this is executed in one threading.Thread object
def producer():
    global QUEUE_ITEM
    while True:
        i = produce_item()
        QUEUE_ITEM = i

# this is executed in another threading.Thread object
def consumer():
    global QUEUE_ITEM
    while True:
        i = QUEUE_ITEM
        consume_item(i)

我的问题是:这个代码线程安全吗?在

立即评论:这段代码不是真正的无锁的-我使用CPython,它有GIL。在

我测试了一点代码,它似乎可以工作。它转化为一些装载和存储操作,因为GIL是原子的。但我也知道当x实现__del__方法时,del x操作不是原子的。因此,如果我的项目有一个__del__方法,并且发生了一些令人讨厌的调度,事情可能会中断。还是没有?在

另一个问题是:为了使上面的代码正常工作,我必须施加什么样的限制(例如对生产的项目的类型)?在

我的问题只是理论上是否有可能利用CPython和GIL的怪癖来实现无锁(即没有锁穿线。锁定在代码中显式地)解决方案。在


Tags: 项目代码queue产品is模式消费者this
3条回答

是的,这将按照您描述的方式工作:

  1. 生产者可能会产生一个可跳过的元素。在
  2. 消费者可以消费相同的元素。在

But I also know that del x operation isn't atomic when x implements del method. So if my item has a del method and some nasty scheduling happens, things may break.

我没看到“德尔”这个词。如果del发生在consume_item中,则del可能发生在producer线程中。我不认为这是个“问题”。在

不过,不用费心用这个。在无意义的轮询周期中,您将耗尽CPU,而且这并不比使用带锁的队列快,因为Python已经有了全局锁。在

这不是真正的线程安全的,因为生产者可以在消费者消费之前覆盖QUEUE_ITEM,而消费者可以消费QUEUE_ITEM两次。正如你提到的,你可以接受,但大多数人不同意

对cpython内部有更多了解的人将不得不回答更多的理论问题。在

诡计会咬你的。只需使用队列在线程之间通信。在

相关问题 更多 >