您的位置:

17. Python 中的锁对象——可重入锁

Python 中的锁对象——可重入锁

更新:

如果您尝试运行下面提供的代码,锁对象将在第一次调用acquire()方法时获得锁,但第二次不会。

为什么会这样?因为正常的锁对象一旦被获取就不能被重新获取,即使相同的线程试图这样做。

但是为什么会有人尝试两次调用acquire()方法呢?让我们举一个简单的例子来演示这个简单的锁定问题:

lock = threading.Lock()

def get_first_line():
    lock.acquire()
    try:
        # read some file and get the first line
    finally:
        lock.release()
    return data

def get_second_line():
    lock.acquire()
    try:
        # read the same file and get the second line
    finally:
        lock.release()
    return data

在上面的代码中,我们有两个不同的函数从共享资源中读取不同部分的数据。我们使用了锁定机制来防止任何其他线程在我们的线程读取文件时修改文件的数据。

现在考虑您想要逐个调用这两个函数,您将这样做:

first = get_first_line()
second = get_second_line()

return first, second 

但是这个调用仍然不是线程安全的,因为当您从共享资源中读取数据时,在两个函数调用之间可以有任何其他线程可以修改共享资源的内容。

为了避免这种情况,我们可以获取一个锁,然后调用这两个函数:

lock.acquire()

try:
    first = get_first_line()
    second = get_second_line()
finally:
    lock.release()
return first, second 

但是,这段代码不会起作用,因为我们将在同一线程内的锁对象上调用acquire(),试图在调用函数之前已经获取的函数内再次获取锁。

因此,在这种情况下,不能使用基本的锁对象。对于这样的情况我们有RLock类。


对象:Python 多线程

RLock 代表可重入锁。同一个线程可以多次获取可重入锁。

RLock 对象也有两个可以调用的方法,它们是:

  1. acquire()方法
  2. release()方法

这里有一个简单的例子来演示RLock对象的工作:

如果我们使用RLock对象,那么简单的锁定问题示例中的代码也将毫无问题地工作:

lock = threading.RLock()

lock.acquire()

try:
    first = get_first_line()
    second = get_second_line()
finally:
    lock.release()
return first, second 

上面的代码可以正常工作。