【问题标题】:Python multithreading and Global Interpreter LockPython 多线程和全局解释器锁
【发布时间】:2017-09-14 05:08:35
【问题描述】:

我最近遇到了 Python 中的 GIL,根据该 GIL,一次只能执行一个线程,而多线程不能利用所有内核。

现在在我的一个项目中,我使用了多线程以及大量的锁和信号量 所以在这里我的问题是,如果我不使用锁和信号量,我能达到同样的效果吗?即如果我从我的项目中删除并发逻辑。

编辑:我想知道的是,如果我删除并发逻辑是否可以获得相同的功能,我知道 GIL 是什么,它会阻止线程使用所有内核并且一次只运行一个线程。

【问题讨论】:

  • 如果有帮助,Project 不受 I/O 限制,它的 CPU 密集型。
  • @AmitGupta 它没有回答我的问题,即如果所有线程由于 GIL 的存在而没有同时运行,是否仍然需要使用锁和信号量来保护共享资源。
  • @VINAYCHAUHAN 是的,如果您有多个线程和共享资源,即使存在全局解释器锁,您仍必须使用互斥锁序列化对它们的访问
  • 你永远不知道你什么时候会失去 GIL,它可能在一个包含多个字节码指令的操作之间。

标签: python multithreading gil


【解决方案1】:

全局解释器锁确保只有一个线程同时执行字节码。该执行随时可能中断。

考虑这个简单的函数,它可能旨在以原子方式将相关值存储到实例上的属性x

def f(x, a, b):
    x.a, x.b = a, b

这是它的反汇编成字节码

          0 LOAD_FAST                1 (a)
          3 LOAD_FAST                2 (b)
          6 ROT_TWO
          7 LOAD_FAST                0 (x)
         10 STORE_ATTR               0 (a)
         13 LOAD_FAST                0 (x)
         16 STORE_ATTR               1 (b)
         19 LOAD_CONST               0 (None)
         22 RETURN_VALUE

假设x 不受mutex 保护。然后,任何执行f(x, 1, 2) 的线程都可以在存储a10)和存储b16)之间轻松中断。该中断线程现在将看到 x 处于不一致状态。

【讨论】:

  • 所以你想说如果 GIL 持有锁,它不会切换线程 btw 你的回答确实为我清除了事情。
  • @VINAYCHAUHAN 不,我不是这么说的。 GIL 仍将尝试切换线程...但是如果您使用互斥锁来保护原始线程具有 acquiredx,那么新切换的线程不可能acquire 那个互斥锁并查看@987654335 @ 处于不一致的状态。
  • 好吧,我相信这是一个更大的问题,假设我有 100 个线程并且每个线程都访问相同的资源,现在如果在线程持有互斥锁时有上下文切换,那么整个程序(所有线程)阻塞,直到上下文更改为原始线程并释放锁。
  • @VINAYCHAUHAN 令人惊讶的是,您可能会发现 python 开发人员已经想到了这一点…… GIL 仅适用于解释字节码的代码。互斥量获取是不需要 GIL 的 C 代码。新线程在尝试获取互斥锁时将在 C 代码中阻塞,将 GIL 重新分配给另一个线程。您并没有突然发现 Python 线程设计中存在过去十年无人注意到的巨大漏洞。
  • @donkopotamus 我认为为了防止您在示例中提到的问题,我们有 GIL。因为在 GIL 的情况下,完整的组装块将成为锁定和解锁序列的一部分。我认为 GIL 不会允许任何不一致,除非你完全杀死整个程序,我猜在这种情况下没有锁定语义世界可以预防。
猜你喜欢
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
相关资源
最近更新 更多