Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python内置容器是线程安全的吗?_Python_Thread Safety - Fatal编程技术网

Python内置容器是线程安全的吗?

Python内置容器是线程安全的吗?,python,thread-safety,Python,Thread Safety,我想知道Python内置容器(列表、向量、集…)是否是线程安全的?或者我需要为我的共享变量实现一个锁定/解锁环境吗?只要不禁用线程的GIL in C代码,它们就是线程安全的。您需要为所有将在Python中修改的共享变量实现自己的锁定。您不必担心从不会被修改的变量中读取数据(即,并发读取是可以的),因此不可变类型(frozenset,tuple,str)可能是安全的,但不会造成伤害。对于您将要更改的内容——list、set、dict,以及大多数其他对象,您应该有自己的锁定机制(虽然在大多数对象上就

我想知道Python内置容器(列表、向量、集…)是否是线程安全的?或者我需要为我的共享变量实现一个锁定/解锁环境吗?

只要不禁用线程的GIL in C代码,它们就是线程安全的。

您需要为所有将在Python中修改的共享变量实现自己的锁定。您不必担心从不会被修改的变量中读取数据(即,并发读取是可以的),因此不可变类型(
frozenset
tuple
str
)可能是安全的,但不会造成伤害。对于您将要更改的内容——
list
set
dict
,以及大多数其他对象,您应该有自己的锁定机制(虽然在大多数对象上就地操作是可以的,但线程可能会导致非常严重的错误——您还可以实现锁定,这非常简单)

顺便说一句,我不知道您是否知道这一点,但是在Python中锁定非常容易-创建一个threading.lock对象,然后您可以像这样获取/释放它:

import threading
list1Lock = threading.Lock()

with list1Lock:
    # change or read from the list here
# continue doing other stuff (the lock is released when you leave the with block)
在Python2.5中,使用u语句从uu未来uu导入;Python2.4及之前版本没有此功能,因此您需要将acquire()/release()调用放入
try:…finally:
块中:

import threading
list1Lock = threading.Lock()

try:
    list1Lock.acquire()
    # change or read from the list here
finally:
    list1Lock.release()
# continue doing other stuff (the lock is released when you leave the with block)

是的,但你当然还是要小心

例如:

如果两个线程从只有一个项目的列表中竞相运行到
pop()
,则一个线程将成功获取该项目,另一个线程将获取
索引器

这样的代码不是线程安全的

if L:
    item=L.pop() # L might be empty by the time this line gets executed
你应该这样写

try:
    item=L.pop()
except IndexError:
    # No items left

队列模块实现多生产者、多消费者队列。当信息必须在多个线程之间安全地交换时,它在线程编程中特别有用。此模块中的Queue类实现所有必需的锁定语义


这是CPython的一个实现细节,您不应该依赖它。它在未来可能会有机会,而其他的实现却没有。Georg——python的这一方面让我感到恐惧。当8个内核在桌面上变得普遍时,java程序会丢失所有的bug——当GIL被删除,多线程python应用程序突然在8个内核上运行时会发生什么?如果他们不假装自己的代码是线程安全的,而显然不是线程安全的,这不应该吓坏任何人Kylotan——我认为这是开玩笑(希望这是正确的!),但以下仍然值得一提。你(或任何人)能切记地说他们从来没有写过没有种族限制的多线程代码吗?我可能认为我做到了,但我足够现实地承认,我并没有在所有情况下都做到这一点。GIL是一个安全网,在这方面可能会给人错误的信心,灌输坏习惯,当/如果默认python容器在8台以上的PC机很普遍的时候清除GIL,这些坏习惯就会被扫除。这可能是一个没有实际意义的问题,有人说吉尔永远不会去。时间会证明一切的@piotrdorgost:GIL并不存在于所有Python实现中Jython和IronPython没有GIL,可以充分利用多处理器系统。另外,从长远来看,CPython试图摆脱GIL。我认为,对于以前没有使用线程锁的人来说,应该注意,锁(在您的示例中,
list1Lock
)应该在线程之间共享,以便它能够正常工作。两个独立的锁,每个线程一个,将不会锁定任何东西,只是添加愚蠢的开销。不应该是这样:用List1LoC:YO做填充,但是考虑一下:“在实践中,它意味着对构建数据类型(int,列表,DICT等)的共享变量的操作确实是“原子”的。”()所以这样的操作是线程安全的?“但它不会伤害”。。。Python文档只是偶尔保证线程安全(例如)。因此,如果要编写适用于所有实现的代码,通常需要锁。然而,许多人只关心自己的python实现。例如,在CPython中,许多收集方法都是线程安全的(并且在将来可能会保持这种状态,因为许多代码都依赖于此)。锁定可能会带来很大的开销;为了避免这种情况,可能需要依赖于特定于实现的行为。我希望pop()是线程安全的,但在文档中找不到这一事实。在我把它当作福音之前,有人能帮我找到这个说法的来源吗?真的吗?list.pop()不是线程安全的吗?我看到另一篇文章声称相反@中军“马克”金和说它是线程安全的。。但这并不意味着你不必考虑其他线程。如他所说,如果一个线程弹出最后一个项目,然后另一个线程也尝试弹出,它将得到IndexError。