首页 > 解决方案 > multiprocessing.Lock 是否在其上下文中暂停程序?

问题描述

我想知道 GIL Lock 类是否暂停程序或跳过其中的上下文,以防锁被另一个线程持有

from multiprocessing import Lock
from threading import Thread
import pandas as pd

# Thread 1
def th1(lock1):
    while True:
        with lock1:  # does the program pause/wait here in case lock is held by Th2 or simply skip the context within lock1?
            df1 = pd.read_csv('foo.csv')
        # do some work with df1

# Thread 2
def th2(lock2):
    while True:
        with lock2:  # does the program pause/wait here in case lock is held by Th1 or simply skip the context within lock2?
            df2 = pd.read_csv('foo.csv')
        # do some work with df2

if __name__ == "__main__":

    th_lock = Lock()
    th1_th = Thread(target=th1, daemon=False, kwargs:{'lock1':th_lock}
    th2_th = Thread(target=th2, daemon=False, kwargs:{'lock2':th_lock}
    th1_th.start()
    th2_th.start()

标签: pythonlockingpython-multiprocessing

解决方案


简单的答案

如果Lockwith语句中使用 a ,它将阻塞线程,直到获得锁,然后执行套件:

with some_lock:
    do_all_the_things() 

如果你想偷看锁,你可以手动获取,如果成功则只执行锁定的代码

if some_lock.acquire(block=False):
    try:
        do_all_the_things() # only executed if lock acquired immediately
    finally:
        some_lock.release()

或者,对于超时

if some_lock.acquire(timeout=4.2):
    try:
        do_all_the_things() # only executed if lock acquired before timeout
    finally:
        some_lock.release()

复杂的答案

获取锁的步骤因操作系统而异,但一般步骤是

  • 尝试获得锁
  • 成功,返回
  • 释放吉尔
  • 等待锁
  • 获得吉尔
  • 返回

获得锁的第一个实体继续执行,而不对 GIL 进行任何更改。它在锁上有 GIL(或者它不会运行来获取锁),并将在定期检查间隔释放它以让其他线程运行。

现在另一个线程正在运行并尝试获取锁。该操作释放 GIL,然后等待锁定。由于第一个实体除了等待 GIL 之外没有被阻塞,它再次运行并完成其业务。当它终于可以释放锁时,第二个实体的非 GIL C 代码运行一点点以尝试获取 GIL。但它卡在那里,因为第一个实体仍然有 GIL。

第一个实体将在定期检查间隔终止或释放 GIL,让第二个条目在受锁保护的代码内运行。

请注意,第一个或第二个实体都没有被阻止。它们将根据另一个释放 GIL 的时间进行交错。假设您正试图保护锁中的数据结构。好吧,其他代码正在运行。如果它在锁之外摆弄相同的数据,那么你就有了一个错误。锁没用。这是合作锁定。它只有在每个人都玩游戏时才有效。


推荐阅读