【问题标题】:Python gil strange behaviourPython gil 奇怪的行为
【发布时间】:2017-06-29 08:15:02
【问题描述】:

看这段代码:

from threading import Thread
import time

cpt = 0

def myfunction():
    print("myfunction.start")
    global cpt
    for x in range(10):
        cpt += 1
        time.sleep(0.2)
        print("cpt=%d" % (cpt))
    print("myfunction.end")

thread1 = Thread(target=myfunction)
thread2 = Thread(target=myfunction)
thread1.start()
thread2.start()

这是一个读取/写入全局变量的非常基本的函数。 我在同一个函数上运行 2 个线程。

我读到 python 在多线程方面效率不是很高,因为 GIL 会自动锁定访问相同资源的函数或方法。 所以,我在想python会先运行thread1,然后是thread2,但我可以在控制台输出中看到2个线程是并行运行的。 所以我不明白gil真正锁定的是什么......

谢谢

【问题讨论】:

  • GIL 与“访问相同的资源”无关。
  • GIL 锁定在 Python 字节码级别,而不是函数或方法。

标签: python multithreading gil


【解决方案1】:

这是因为 sleep 系统调用释放了 CPU(甚至从解释器“退出”了一段时间)

当您执行time.sleep(0.2) 时,当前线程会被系统(而不是 Python)挂起一段给定的时间,并允许其他线程工作。

请注意,您可以插入以监视线程的print 语句或threading.current_thread() 也会(简要地)向系统屈服,因此线程可以因此而切换(请记住Schrodinger's cat)。 真正的测试是这样的:

from threading import Thread
import time

cpt = 0

def myfunction():
    global cpt
    for x in range(10):
        cpt += 1
        time.sleep(0.2)
    print(cpt)

thread1 = Thread(target=myfunction)
thread2 = Thread(target=myfunction)
thread1.start()
thread2.start()

给你

20
20

这意味着每个线程依次增加计数器。

现在评论time.sleep() 语句,你会得到:

10
20

这意味着第一个线程接受了所有的增加,结束并让第二个线程增加另外 10 个计数。没有系统调用(即使是print)确保 GIL 完全工作。

GIL 不会引起 性能 问题,它只是阻止 2 个线程并行运行。如果您需要真正并行运行 python 代码,则必须改用 multiprocessing 模块(及其所有约束,酸洗,分叉......)

【讨论】:

  • 好的,所以 GIL 只会锁定内部 python 调用?正如我所读的那样,gil 是否存在很大的性能问题?谢谢
猜你喜欢
  • 2020-10-22
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
相关资源
最近更新 更多