【发布时间】:2010-01-28 19:13:13
【问题描述】:
在 python 中,我定义了一个由不同线程读取/递增的全局变量。由于 GIL,如果不使用任何类型的锁定机制,这是否会导致问题?
【问题讨论】:
-
您是在谈论使用“线程”模块的实现吗?在这种情况下,您应该使用提供的锁定机制:请参阅docs.python.org/library/threading.html
在 python 中,我定义了一个由不同线程读取/递增的全局变量。由于 GIL,如果不使用任何类型的锁定机制,这是否会导致问题?
【问题讨论】:
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)以保持数据一致性。
【讨论】:
dis.dis("x=753") 输出?我更正了代码。
__getitem__ 或__add__ 或任何其他场景调用更多的python 代码。然后你最终会在一个字节码中途交换线程。
是的,没有锁定的多线程几乎总是会导致问题,不管有没有 GIL。
【讨论】: