在阅读了各种解释 GIS 和 Python 线程的文章之后,以及由于 GIL 而在多线程 Python 代码中是否不需要锁?这是一个非常有用的答案,我有一个“最后一个问题”。
理想情况下,如果我的线程仅通过原子(Python VM)指令对共享数据进行操作,例如将项目附加到列表,则不需要锁,对吗?
在阅读了各种解释 GIS 和 Python 线程的文章之后,以及由于 GIL 而在多线程 Python 代码中是否不需要锁?这是一个非常有用的答案,我有一个“最后一个问题”。
理想情况下,如果我的线程仅通过原子(Python VM)指令对共享数据进行操作,例如将项目附加到列表,则不需要锁,对吗?
这实际上取决于您的应用程序。就像在任何其他语言中一样,您可能需要针对特定用例的锁,但无论如何您都不需要保护 python 对象被损坏。从这个意义上说,您不需要锁。
这是一个使用大量原子操作的示例,但是当您将它们组合起来时,它们仍然会以意想不到的方式运行。
线程 1:
v = l[-1]
DoWork(v]
del l[-1]
线程 2:
l.append(3)
如果线程 2 在线程 1 的第一条语句和最后一条语句之间运行,那么线程 1 只是删除了错误的工作项。python 对象都没有损坏或任何东西,但您仍然得到意外结果,并且可能会引发异常。
如果你有共享数据结构,你通常需要用锁来保护它们,或者甚至更好地使用已经编写的保护版本,比如在这种情况下可能是一个队列:http ://docs.python.org/library/queue.html
理论上不是,但这取决于逻辑,例如,当您保持订单时,您需要一个锁。
当您在线程之间共享数据时,您应该始终确保您的数据正确同步,因为您不能依赖未来的操作是否是原子的。
与尝试修复由于实现更改或错误假设而导致的中断相比,首先获得正确的多线程设计要容易得多。
谢谢大家的回答!很明显,线程同步要求与应用程序逻辑绑定,但我可以依靠 GIL 来不破坏内置对象的内部结构(操作是原子的)。当我说 GIL 保护解释器的“内部状态”时,我不清楚它的内部数据结构......我的意思是,这是一种效果,但 GIL 保护每个分配的内置结构,包括对象由解释器的内部操作和应用程序创建的对象创建和使用。那是我的疑问。
PS:很抱歉这么晚才回复,但我没有收到电子邮件通知...