python如何知道当前线程是否持有锁

时间:2014-05-13 15:23:34

标签: python multithreading python-2.7 python-multithreading

我有一个threading.Lock对象,我想知道current_thread是否持有此锁。实现这一目标的最简单方法是什么?

3 个答案:

答案 0 :(得分:6)

对于我所知道的threading.Lock个对象,没有直接的方法可以做到这一点。那些具有locked属性,但在所有线程中都会显示为True,而不仅仅是拥有线程。可以使用RLock,但您必须访问RLock对象上的内部__owner属性,这是不可取的或保证始终有效。要做的代码看起来像这样,值得:

#!/usr/bin/python

import threading
import time

def worker():
    if l._RLock__owner is threading.current_thread():
        print "I own the lock"
    else:
        print "I don't own the lock"
    l.acquire()
    if l._RLock__owner is threading.current_thread():
        print "Now I own the lock"
    else:
        print "Now I don't own the lock"
    time.sleep(5)
    l.release()

if __name__ == "__main__":
    l = threading.RLock()
    thds = []
    for i in range(0, 2): 
        thds.append(threading.Thread(target=worker))
        thds[i].start()

    for t in thds:
        t.join()

这是输出:

dan@dantop:~> ./test.py
I don't own the lock
Now I own the lock
I don't own the lock

但实际上,你的代码真的不应该这样做。为什么你觉得你需要这个明确的检查?通常,当您编写代码块时,您将知道是否已在该上下文中获取锁定。你能分享一个你认为需要检查它的例子吗?

答案 1 :(得分:1)

release方法的帮助文字:

Help on built-in function release:

release(...)
    release()

    Release the lock, allowing another thread that is blocked waiting for
    the lock to acquire the lock.  The lock must be in the locked state,
    but it needn't be locked by the same thread that unlocks it.

这意味着Lock对象并不关心谁锁定它们,因为任何线程都可以解锁它们。因此,对于未修改的锁定对象,无法确定当前线程是否是持有锁定的线程,因为没有线程"持有"锁 - 它只是锁定或解锁。

我认为你想要知道你是否持有锁的原因是你没有尝试获得锁定。例如:

def a():
    with theLock:
        do_stuff()
        b()
        do_other_stuff()

def b():
    with theLock:
        do_b_stuff()

此处,如果线程尚未拥有锁,您只想在theLock中获取b()。正如我在评论中提到的,这是一个重入锁的完美用例。如果您创建这样的锁:

theLock = threading.RLock()

然后我提供的示例工作正常 - 当您调用a()时,它获取锁定。然后在b()中,它允许您重新获取锁定而不会抱怨。此外,如果您使用上下文管理器语法(with theLock:),您将不必担心一个警告。

需要注意的是,如果您手动拨打acquirerelease,则需要确保每次拨打release时都拨打acquire一次。在上面的示例中,如果我在theLock.acquire()a()中都调用了b(),那么我也需要在这两个函数中调用release()。如果你只调用acquire两次而release只调用一次,那么该线程仍将保持锁定,使其他线程无法获取锁定。

答案 2 :(得分:0)

请查看Thread Synchronization Mechanisms

您可以尝试以下

import threading
lock = threading.Lock()
lock.acquire()

#now  that the lock is taken, using lock.acquire(False) will return False
if not lock.acquire(False):
    # could not lock the resource

现在添加一个扭曲:

import threading

class customLock(object):
    _accessLock = threading.Lock()
    def __init__(self):
        self._lock = threading.Lock()
        self.ownerThread = None

    def acquire(self, thread):
        self._accessLock.acquire()
        try:
            if self._lock.acquire():
                self.ownerThread = thread
        finally:
            self._accessLock.release()

    def release(self):
        self._accessLock.acquire()
        try:
            self._lock.release()
            self.ownerThread = None
        finally:
            self._accessLock.release()



    def getOwner(self):
        return self.ownerThread

    def acquire(self, blocking=True): 
        return self._lock.acquire(blocking)

将初始示例转换为:

import threading
lock = customLock()
lock.acquire(threading.current_thread())


#now  that the lock is taken, using lock.acquire(False) will return False
if not lock.acquire(False):
    # could not lock the resource
    if lock.getOwner() is threading.current_thread():
        # do something

希望这有帮助