首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >多线程Python代码中的锁是否是因为GIL而不必要的?

多线程Python代码中的锁是否是因为GIL而不必要的?
EN

Stack Overflow用户
提问于 2008-09-19 20:07:38
回答 3查看 10.2K关注 0票数 77

如果你依赖一个拥有全局解释器锁(即CPython)的Python实现并编写多线程代码,那么你真的需要锁吗?

如果GIL不允许并行执行多条指令,那么共享数据难道不需要保护吗?

如果这是一个愚蠢的问题,很抱歉,但这是我一直想知道的关于多处理器/核心计算机上的Python的事情。

同样的事情也适用于任何其他具有GIL的语言实现。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2008-09-19 20:34:41

如果你在线程之间共享状态,你仍然需要锁。GIL只在内部保护解释器。你仍然可以在你自己的代码中有不一致的更新。

例如:

代码语言:javascript
复制
#!/usr/bin/env python
import threading

shared_balance = 0

class Deposit(threading.Thread):
    def run(self):
        for _ in xrange(1000000):
            global shared_balance
            balance = shared_balance
            balance += 100
            shared_balance = balance

class Withdraw(threading.Thread):
    def run(self):
        for _ in xrange(1000000):
            global shared_balance
            balance = shared_balance
            balance -= 100
            shared_balance = balance

threads = [Deposit(), Withdraw()]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

print shared_balance

在这里,您的代码可能会在读取共享状态(balance = shared_balance)和写回更改后的结果(shared_balance = balance)之间中断,从而导致更新丢失。结果是共享状态的随机值。

为了使更新保持一致,run方法需要锁定读取-修改-写入部分周围的共享状态(在循环内),或者使用some way to detect when the shared state had changed since it was read

票数 72
EN

Stack Overflow用户

发布于 2008-12-22 09:49:36

这样想吧:

在单处理器计算机上,多线程发生的方式是挂起一个线程,然后以足够快的速度启动另一个线程,使其看起来像是同时运行。这就像使用GIL的Python :只有一个线程在实际运行。

问题是线程可以在任何地方挂起,例如,如果我想计算b= (a + b) * 3,这可能会产生类似如下的指令:

代码语言:javascript
复制
1    a += b
2    a *= 3
3    b = a

现在,假设它在一个线程中运行,该线程在第1行或第2行之后挂起,然后另一个线程开始运行:

代码语言:javascript
复制
b = 5

然后,当另一个线程恢复时,b将被旧的计算值覆盖,这可能不是预期的。

因此,您可以看到,即使它们实际上没有同时运行,您仍然需要锁定。

票数 4
EN

Stack Overflow用户

发布于 2008-09-19 20:11:19

您仍然需要使用锁(您的代码可能在任何时候被中断以执行另一个线程,这可能会导致数据不一致)。GIL的问题是它阻止Python代码同时使用更多的内核(或多个处理器,如果它们可用的话)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/105095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档