gpt4 book ai didi

python - Python 中 GIL 的新实现是否处理了竞争条件问题?

转载 作者:行者123 更新时间:2023-12-05 00:46:52 24 4
gpt4 key购买 nike

我已阅读 an article关于 Python 中的多线程,他们试图使用同步来解决竞争条件问题。我已经运行下面的示例代码来重现竞争条件问题:

import threading 

# global variable x
x = 0

def increment():
"""
function to increment global variable x
"""
global x
x += 1

def thread_task():
"""
task for thread
calls increment function 100000 times.
"""
for _ in range(100000):
increment()

def main_task():
global x
# setting global variable x as 0
x = 0

# creating threads
t1 = threading.Thread(target=thread_task)
t2 = threading.Thread(target=thread_task)

# start threads
t1.start()
t2.start()

# wait until threads finish their job
t1.join()
t2.join()

if __name__ == "__main__":
for i in range(10):
main_task()
print("Iteration {0}: x = {1}".format(i,x))

当我使用 Python 2.7.15 时,它确实返回了与文章相同的结果。但是当我使用 Python 3.6.9 时它不会(所有线程返回相同的结果 = 200000)。

我想知道 GIL 的新实现(自 Python 3.2 起)是否处理​​了竞争条件问题?如果是这样,为什么 Lock、Mutex 仍然存在于 Python >3.2 中。如果没有,为什么像上例那样运行多线程修改共享资源时没有冲突?

这些天来,当我试图更多地了解 Python 的底层工作原理时,我的大脑一直在为这些问题苦苦挣扎。

最佳答案

您所指的更改是将检查间隔替换为切换间隔。这意味着不是每 100 字节代码切换一次线程,而是每 5 毫秒切换一次。

引用:https://pymotw.com/3/sys/threads.html https://mail.python.org/pipermail/python-dev/2009-October/093321.html

因此,如果您的代码运行得足够快,它将永远不会经历线程切换,并且您可能会觉得这些操作是原子的,而实际上并非如此。没有出现竞争条件,因为没有实际的线程交织。 x += 1 实际上是四个字节码:

>>> dis.dis(sync.increment)
11 0 LOAD_GLOBAL 0 (x)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_GLOBAL 0 (x)
10 LOAD_CONST 2 (None)
13 RETURN_VALUE

解释器中的线程切换可以发生在任意两个字节码之间。

考虑到在 2.7 中,这总是打印 200000,因为检查间隔设置得如此之高,以至于每个线程在下一次运行之前全部完成。同样可以用开关间隔来构造。

import sys
import threading

print(sys.getcheckinterval())
sys.setcheckinterval(1000000)

# global variable x
x = 0

def increment():
"""
function to increment global variable x
"""
global x
x += 1

def thread_task():
"""
task for thread
calls increment function 100000 times.
"""
for _ in range(100000):
increment()

def main_task():
global x
# setting global variable x as 0
x = 0

# creating threads
t1 = threading.Thread(target=thread_task)
t2 = threading.Thread(target=thread_task)

# start threads
t1.start()
t2.start()

# wait until threads finish their job
t1.join()
t2.join()

if __name__ == "__main__":
for i in range(10):
main_task()
print("Iteration {0}: x = {1}".format(i,x))

关于python - Python 中 GIL 的新实现是否处理了竞争条件问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59436505/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com