Python GIL and globals

4
在Python中,我定义了一个全局变量,被不同的线程读取/增加。由于GIL的存在,如果没有使用任何锁机制,这会造成问题吗?

你是在谈论使用“threading”模块的实现吗? 在这种情况下,您应该使用提供的锁定机制:请参阅http://docs.python.org/library/threading.html - avpx
2个回答

6

GIL(全局解释器锁)只需要在另一个线程接管前,解释器完全执行单个字节码指令。但是,没有理由认为递增操作是单个指令。例如:

>>> import dis
>>> dis.dis(compile("x=753","","exec"))
  1           0 LOAD_CONST               0 (753)
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE
>>> dis.dis(compile("x+=1","","exec"))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (1)
              6 INPLACE_ADD
              7 STORE_NAME               0 (x)
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

正如您所看到的,即使是这些简单的操作也不只是一个字节码指令。因此,每当在线程之间共享数据时,您必须使用单独的锁定机制(例如,threading.lock),以维护数据一致性。


2
哎呀,我是说,三个赞,没人注意到 dis.dis("x=753") 的输出吗?我已经纠正了代码。 - tzot
这是一个例子,我应该更加注意我所写的内容 - 谢谢 :). 同时,它更清晰地显示了这一点 - 在加载值之后,有几个指令才会再次存储该值。 - Daniel G
这甚至不是百分之百的真实情况。字节码(几乎所有)实际上可以通过__getitem____add__或任何其他情况调用更多的Python代码。然后,您最终会在单个字节码中间出现线程交换。 - fijal

3

是的,无锁多线程几乎总会导致问题,无论有没有GIL。


2
请注意,全局解释器锁(GIL)并不是用来保护应用程序数据的;它仅用于保护一些 Python 内部结构,例如 Python 对象的引用计数。您仍需要锁定自己的数据结构。 - S.Lott
2
没错。GIL保护Python免受自身的影响,但它对你并没有任何保护作用。 - Greg Hewgill
1
当然,绝大多数Python执行引擎甚至没有GIL。 - Jörg W Mittag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接