获取阻塞锁是否被阻塞

Get whether a blocking lock blocked

在Python 3,我想获取一个锁,然后知道是否阻塞。问题是 threading.Lock.acquire 总是 return s True 如果用 blocking=True 调用,所以没有办法判断锁在函数被调用。以此代码为例:

import threading

foo = None
lock = threading.Lock()

def bar():
    global foo
    # Only compute foo in one thread at a time.
    if not lock.acquire(blocking=False):
        # The race condition exists here.
        # Another thread is already computing foo.
        # This instance does not need to recompute foo.
        # Wait for that instance to finish.
        with lock:
            # Just return the value that the other instance computed.
            return foo
    # No other instance of this function is computing foo.
    with lock:
        # Compute foo.
        foo = [something]
        return foo

这里的问题是 lock 可以在上面代码中的注释表明存在竞争条件的情况下再次获取。

如果这是因为第三个线程在函数中的同一点首先继续并获取了锁,这是不可取的,因为它引入了轻微的延迟。确实没有理由 return foo 需要保护;两个线程应该可以同时做。

但是,如果获取是由于另一个线程重新计算 foo,那么这是不可取的,因为一旦释放锁,foo 就会发生变化。该函数应该 return 调用时正在计算的 foo 的值。如果 foo 发生变化,则它不能再 return 该值。

理想情况下,我们会有一个 acquire 函数可以阻塞并且仍然 return 无论它是否被阻塞。这样,我们可以自信地断言函数总是 returns 是调用函数时正在计算的 foo 的值,并且只有当 foo 尚未被计算时才会函数然后继续计算它,然后 return 新值。这可以在 Python 中完成吗?

我知道这个问题很老了,但由于我在寻找其他问题时偶然发现了它并且没有得到解答,所以我想我会为任何发现它的人提供服务并回答它。

您首先检查锁是否可用导致了竞争条件。你应该尝试在不检查的情况下获取锁,像这样:

import threading

foo = None
lock = threading.Lock()

def bar():
    global foo
    # Only compute foo in one thread at a time.
    with lock:
        # Only compute foo once.
        if foo is None:
            foo = [something]
        # Just return the value that is now guaranteed to be computed.
        return foo