如何在Python线程中读取没有锁定的变量?

How to read a variable without lock in Python threads?

提问人:SHM 提问时间:1/9/2022 更新时间:1/10/2022 访问量:1315

问:

我正在使用 Python 线程同时完成一些工作。我让主线程执行,并创建一个线程同时执行。以下是我正在处理的代码的简化版本:task_Atask_B

import threading
import numpy as np

def task_B(inc):
    for elem in array:
        value = elem + inc

if __name__ == '__main__':

    array = np.random.rand(10)

    t1 = threading.Thread(target=task_B, args=(1))
    t1.start()

    # task_A
    array_copy = list()
    for elem in array:
        array_copy.append(elem)

    t1.join()

我知道上面的代码没有做一些有意义的事情。请把它看作一个简化的例子。如您所见,变量在主线程和新创建的线程中都是只读的。因此,没有必要同时锁定主线程和线程,因为它们都不会修改(或写入)变量。但是,当我对代码进行计时时,似乎 Python 线程会自动锁定线程之间共享的变量,即使它们是只读的。有没有办法在不锁定只读变量的情况下让每个线程同时运行?我已经找到了这段代码,但不知道如何将其应用于我的情况。arrayt1arrayt1

Python 多线程 锁定 readwritelock

评论

0赞 gold_cy 1/9/2022
你是什么意思?当然,它被锁定了,你有一个线程在数组上工作,而另一个线程正在尝试从中读取。其中一个在修改状态的同时,另一个正在尝试读取状态,您有一个数据争用条件,而没有在此处锁定
1赞 azelcer 1/9/2022
您正在发现 CPytjon 的 GIL
0赞 SHM 1/10/2022
@gold_cy 两个线程都在访问变量,但它们只是在读取它,而不是修改它。(主线程只是读入 s 并将它们附加到另一个列表中,线程读入并将它们保存到 with added,实际上并没有改变它本身。所以我相信不需要锁。elemarrayt1elemarrayvalueincarray

答:

1赞 Lenormju 1/10/2022 #1

你说得对,在这种情况下“不需要锁”,但 CPython 解释器(我猜你用来运行 Python 代码)并不是那么聪明。
Python 代码总是在持有 GIL 的同时执行,因此两个线程都以交错的方式执行(而不是同时执行),尽管以交错的方式执行(没有线程则不会如此,执行将纯粹是顺序的)。
这就是为什么性能关键代码经常被卸载到其他*进程(使用多处理)或用Cython编写的原因(这里是一个解决与你类似的问题的示例)。
有关为什么存在 GIL 的更多详细信息,请参阅该问题:有没有办法使用纯 python 为纯函数释放 GIL?

希望在未来(2022+)Gil 可能会放松,但现在你被它困住了,所以要解决它。