【问题标题】:Thread condition variables: un-acquired lock线程条件变量:未获得的锁
【发布时间】:2014-04-16 17:38:17
【问题描述】:

我在 Python 中有这个示例,它演示了条件变量的使用。

import logging
import threading
import time

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s (%(threadName)-2s) %(message)s',)

def consumer(cond):

    # wait for the condition and use the resource

    logging.debug('Starting consumer thread')

    t = threading.currentThread()

    cond.wait()

    logging.debug('Resource is available to consumer')

def producer(cond):

    # set up the resource to be used by the consumer

    logging.debug('Starting producer thread')

    logging.debug('Making resource available')

    cond.notifyAll()


condition = threading.Condition()

# pass each thread a 'condition'
c1 = threading.Thread(name='c1', target=consumer, args=(condition,))
c2 = threading.Thread(name='c2', target=consumer, args=(condition,))
p = threading.Thread(name='p', target=producer, args=(condition,))


# start two threads and put them into 'wait' state
c1.start()
c2.start()

# after two seconds or after some operation notify them to free or step over the wait() function
time.sleep(2)
p.start()

但是,它会在线程上引发运行时错误un-acquired lock。我有一个想法,我需要使用 acquirerelease 函数,但我不确定它们的用法以及它们的作用。

【问题讨论】:

  • 条件在哪里?当消费者拨打wait 时——它在等待什么?当产品调用notify时,它通知人们的事情在哪里?除非有条件(称为“谓词”),否则不能使用条件变量。

标签: python multithreading python-3.x python-2.x


【解决方案1】:

条件是底层Lock 的包装器,提供等待/通知功能。您需要 acquire 一个锁才能释放它 - wait 在后台执行此操作。值得注意的是,一旦它被重新唤醒,它重新获取锁。因此,在获取和释放之间确保互斥,如果有意义的话,wait “yielding” 对锁的控制。

无需手动进行获取/释放,只需使用 Condition 作为上下文管理器:

def consumer(cond):
    with cond:
        cond.wait()

    logging.debug('Resource is available to consumer')

如果由于某种原因你被困在没有上下文管理器的 python 版本上,这相当于:

def consumer(cond):
    try:
        cond.acquire()
        cond.wait()
    finally:
        cond.release()

    logging.debug('Resource is available to consumer')

您通常希望确保只有一个消费者被唤醒,因此经常使用以下成语:

with cond:
    while some_queue.isEmpty():
        cond.wait()
    #get one from queue

因此,您可以notify 任意数量的消费者,一旦队列为空,额外的消费者会立即返回睡眠状态。

【讨论】:

  • 在 Python 2.5 中,由于没有 with 语句,我是否可以将 acquirerelease 放在 wait 函数周围?
  • 您需要用try/finally 包装东西以获得与上下文管理器相同的语义,请参阅编辑。
  • 这个锁有什么作用,为什么需要它?
  • A Lock 确保在给定时间只有一个线程可以进入给定的代码块 - 也就是互斥。你“需要”它只是在Condition 工作的范围内,我不能回答更多。也许你想要做的实际上并不需要条件,但我不能告诉你。
  • that website 上,他们没有将cond.acquire() 放入try 语句中,我会说他们不这样做是对的:这使它更容易理解。当您不知道时,您就像“为什么必须将acquire 放入try 语句中?”。这不是一个相关的问题,因为你不必把它放在那里。顺便说一句,链接的网站对我理解 Python 中的线程有很大帮​​助,希望它可以帮助其他人
猜你喜欢
  • 1970-01-01
  • 2020-05-26
  • 2020-05-15
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2018-10-08
  • 2013-04-01
  • 1970-01-01
相关资源
最近更新 更多