线程条件变量:未获取锁

5 投票
1 回答
18775 浏览
提问于 2025-04-18 03:01

我有一个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()

不过,它在运行时出现了一个错误,提示说是未获取锁,这个错误和线程有关。我觉得我需要使用acquirerelease这两个函数,但我不太确定它们的用法和具体作用是什么。

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

这样你可以“通知”任意数量的消费者,而多余的消费者一旦队列为空就会立刻回去休眠。

撰写回答