线程条件变量:未获取锁
我有一个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()
不过,它在运行时出现了一个错误,提示说是未获取锁
,这个错误和线程有关。我觉得我需要使用acquire
和release
这两个函数,但我不太确定它们的用法和具体作用是什么。
1 个回答
16
条件(Conditions)是一个包裹在底层锁(Lock)周围的工具,它提供了等待和通知的功能。你需要先“获取”一个锁,才能释放它——这就是“等待”(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
这样你可以“通知”任意数量的消费者,而多余的消费者一旦队列为空就会立刻回去休眠。