Python的Global Interpreter Lock的确切功能是什么?其他编译为字节码的语言是否采用类似的机制?
Python的Global Interpreter Lock的确切功能是什么?其他编译为字节码的语言是否采用类似的机制?
Answers:
通常,对于任何线程安全问题,您都需要使用锁来保护内部数据结构。这可以通过各种级别的粒度来完成。
您可以使用细粒度的锁定,其中每个单独的结构都有自己的锁定。
您可以使用粗粒度锁定,其中一种锁定可以保护所有内容(GIL方法)。
每种方法各有利弊。细粒度锁定允许更大的并行度-两个线程不共享任何资源时可以并行执行。但是,这需要更大的管理开销。对于每一行代码,您可能需要获取并释放几个锁。
相反,粗粒度方法则相反。两个线程不能同时运行,但是单个线程将运行得更快,因为它没有做太多记账工作。最终,它归结为单线程速度和并行性之间的折衷。
曾有几次尝试在python中删除GIL,但单线程计算机的额外开销通常太大。实际上,由于锁争用,即使在多处理器机器上,某些情况实际上也会变慢。
其他编译为字节码的语言是否采用类似的机制?
它各不相同,可能不应该将其视为语言属性,而应将其视为实现属性。例如,有些Python实现(例如Jython和IronPython)使用其底层VM的线程方法,而不是GIL方法。此外,下一代Ruby似乎正朝着引入GIL迈进。
Python解释器不是完全线程安全的。为了支持多线程Python程序,当前线程必须拥有一个全局锁,才能安全地访问Python对象。如果没有锁,即使是最简单的操作也可能在多线程程序中引起问题:例如,当两个线程同时增加同一对象的引用计数时,引用计数最终只能被增加一次,而不是两次。
因此,存在这样的规则,即只有已获得全局解释器锁的线程才能在Python对象上操作或调用Python / C API函数。为了支持多线程Python程序,解释器会定期释放并重新获取锁-默认情况下,每100个字节码指令(可以通过sys.setcheckinterval()进行更改)。锁定也被释放并重新获得,这可能会阻止潜在的I / O操作(例如,读取或写入文件),以便在请求I / O的线程正在等待I / O操作完成的同时运行其他线程。
我认为这很好地概括了这个问题。
像perl 5一样,Python并不是从一开始就设计为线程安全的。事实发生之后,线程就被嫁接了,因此全局解释器锁用于维持互斥,即在给定时间在解释器的肠道中只有一个线程在执行代码。
解释器本身通过频繁地循环锁来使各个Python线程协作执行多任务。
当其他Python线程处于活动状态以“选择加入”此协议并确保没有任何不安全的事情发生时,当您从C与Python交谈时,需要自己抓取锁。
具有单线程遗产的其他系统后来又演变为多线程系统,通常具有这种机制。例如,Linux内核在早期SMP时代就具有“大内核锁定”功能。随着多线程性能逐渐成为一个问题,随着时间的流逝,有一种趋势试图将这些类型的锁分解为更小的碎片,或者用无锁算法和数据结构替换它们,以尽可能提高吞吐量。
reiserfs
-我对此一无所知的唯一真实原因)。