multiprocessing.Lock 是否在其上下文中暂停程序?

Does a multiprocessing.Lock pause the program within its context?

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

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()

简单答案

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

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()

复杂的答案

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

  • 尝试获取锁
  • 成功后,return
  • 释放吉尔
  • 等待锁定
  • 获得吉尔
  • return

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

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

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

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