2024-04-26 12:57:23 发布
网友
如果您依赖一个具有全局解释器锁(即CPython)的Python实现并编写多线程代码,那么您真的需要锁吗?
如果GIL不允许多条指令并行执行,那么共享数据就没有必要进行保护吗?
抱歉,如果这是一个愚蠢的问题,但这是我一直想知道的关于多处理器/核心机器上的Python。
同样的事情也适用于任何其他具有GIL的语言实现。
如果在线程之间共享状态,则仍然需要锁。GIL只在内部保护解释器。您自己的代码中仍然可能有不一致的更新。
例如:
#!/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)之间被中断,从而导致丢失更新。结果是共享状态的随机值。
balance = shared_balance
shared_balance = balance
为了使更新保持一致,run方法需要锁定read-modify-write部分周围的共享状态(在循环内)或具有some way to detect when the shared state had changed since it was read。
不-GIL只是保护python内部不受多个线程改变其状态的影响。这是一个非常低级的锁定,仅足以使python自己的结构保持一致的状态。它不包括在您自己的代码中覆盖线程安全所需的应用程序级别锁定。
锁定的本质是确保特定的代码块只由一个线程执行。GIL对单个字节码大小的块强制执行此操作,但通常您希望锁跨越比此更大的代码块。
添加到讨论中:
因为GIL存在,所以有些操作在Python中是原子的,不需要锁。
http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe
然而,正如其他答案所述,只要应用程序逻辑需要锁(例如在生产者/消费者问题中),您仍然需要使用锁。
如果在线程之间共享状态,则仍然需要锁。GIL只在内部保护解释器。您自己的代码中仍然可能有不一致的更新。
例如:
在这里,您的代码可以在读取共享状态(
balance = shared_balance
)和将更改的结果写回(shared_balance = balance
)之间被中断,从而导致丢失更新。结果是共享状态的随机值。为了使更新保持一致,run方法需要锁定read-modify-write部分周围的共享状态(在循环内)或具有some way to detect when the shared state had changed since it was read。
不-GIL只是保护python内部不受多个线程改变其状态的影响。这是一个非常低级的锁定,仅足以使python自己的结构保持一致的状态。它不包括在您自己的代码中覆盖线程安全所需的应用程序级别锁定。
锁定的本质是确保特定的代码块只由一个线程执行。GIL对单个字节码大小的块强制执行此操作,但通常您希望锁跨越比此更大的代码块。
添加到讨论中:
因为GIL存在,所以有些操作在Python中是原子的,不需要锁。
http://www.python.org/doc/faq/library/#what-kinds-of-global-value-mutation-are-thread-safe
然而,正如其他答案所述,只要应用程序逻辑需要锁(例如在生产者/消费者问题中),您仍然需要使用锁。
相关问题 更多 >
编程相关推荐