线程条件变量:未获取的锁定

时间:2014-04-16 17:38:18

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

我在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函数,但我不确定它们的用法以及它们的用途。

1 个答案:

答案 0 :(得分:9)

条件是提供等待/通知功能的基础Lock的包装器。你需要先acquire一个锁才能释放它 - wait做了什么。值得注意的是,一旦它被重新唤醒,重新获取锁定。因此,在获得和释放之间确保互斥,wait"产生"控制锁,如果这是有道理的。

不要手动获取/释放,只需使用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任意数量的消费者和额外的消费者只要在队列为空时立即重新入睡。