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

时间:2010-02-09 06:17:20

标签: python thread-safety

我想知道Python内置容器(list,vector,set ...)是否是线程安全的?或者我是否需要为共享变量实现锁定/解锁环境?

4 个答案:

答案 0 :(得分:43)

您需要为将在Python中修改的所有共享变量实现自己的锁定。您不必担心从不会被修改的变量中读取(即并发读取都没问题),因此不可变类型(frozensettuplestr)是可能安全,但不会受到伤害。对于您将要更改的内容 - listsetdict以及大多数其他对象,您应该拥有自己的锁定机制(在大多数情况下,就地操作都可以其中,线程可能导致超级恶劣的错误 - 您可能也可以实现锁定,这很容易。)

顺便说一下,我不知道你是否知道这一点,但在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)

在Python 2.5中,from __future__ import with_statement; Python 2.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)

Some very good information about thread synchronization in Python

答案 1 :(得分:8)

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

例如:

如果两个帖子从只有一个项目的列表中竞争pop(),则一个线程将成功获得该项目,另一个线程将获得IndexError

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

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

答案 2 :(得分:4)

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

答案 3 :(得分:0)

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

https://docs.python.org/3/library/queue.html