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。如果它在锁之外摆弄相同的数据,那么你就有了一个错误。锁没用。这就是协作锁定。只有每个人都玩游戏才有效。
我想知道 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。如果它在锁之外摆弄相同的数据,那么你就有了一个错误。锁没用。这就是协作锁定。只有每个人都玩游戏才有效。