Python3:我能同时锁定多个锁吗?

3

我有多个锁来锁定我的API的不同部分。

要锁定任何方法,我会像这样做:

import threading

class DoSomething:
    def __init__():
        self.lock = threading.Lock()

    def run(self):
        with self.lock:
            # do stuff requiring lock here

对于大多数使用情况,这样做是可以正常工作的。

但是,当需要多个锁时,我不确定我的操作是否有效:

import threading

class DoSomething:
    def __init__():
        self.lock_database = threading.Lock()
        self.lock_logger = threading.Lock()

    def run(self):
        with self.lock_database and self.lock_logger:
            # do stuff requiring lock here

目前这段代码可以运行,但我不确定它是否按照我的意愿运行。

我的问题是:锁是同时获得还是先获得第一个锁,然后才获取第二个锁。

我的以前的代码是否如下所示?

with self.lock1:
    with self.lock2:
        # do stuff here

目前代码可以正常工作,但由于我的线程同时需要同一把锁的概率极低,因此以后调试可能会带来很大的麻烦。

我提出这个问题是因为我非常不确定如何测试我的代码以确保它按预期工作,并且同样有兴趣得到答案并知道如何测试以确保它工作(而不是最终用户为我测试)。

1个回答

4

可以这样做,但要注意死锁。 当一个线程需要获取另一个线程持有的锁时,它无法取得进展,此时就会发生死锁,因为第二个线程也无法取得进展,因为它想要第一个线程已经持有的锁。

您的代码示例首先锁定lock_database,然后锁定lock_logger。 如果您可以保证锁定它们两个的任何线程始终以相同的顺序锁定它们,则您是安全的。 那样死锁永远不会发生。 但是,如果一个线程在尝试锁定lock_logger之前先锁定lock_database,而某个其他线程尝试以相反的顺序获取它们两个,则会发生死锁。

看起来很容易。 的确如此,除了...

...在更复杂的程序中,其中锁定附加到传递给不同函数的对象上时,可能并不那么容易,因为一个线程可能调用一些foobar(a, b)函数,而另一个线程在相同的两个对象上调用相同的foobar(),只不过对象被交换了。


我知道死锁的存在,但更担心客户遇到问题时,我只能通过电子邮件或者更糟糕的电话来理解情况。 - undefined
我希望我能删除这个回答。不知道为什么楼主接受了它。在我看来,我完全误解了他们的问题。 - undefined
嗯,它确实正确回答了问题。我当时处于一个需要知道是否采用正确方法一次性获取多个锁的上下文中。据我所知,没有with lockA and with lockB:这样的语法,所以你需要逐个获取锁,然后可能会遇到死锁的问题。除非我对某个特性不了解或者误解了答案(可能性存在),它确实回答了问题。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接