【发布时间】:2010-02-09 06:17:20
【问题描述】:
我想知道 Python 内置容器(list、vector、set...)是否是线程安全的?还是我需要为我的共享变量实现锁定/解锁环境?
【问题讨论】:
标签: python thread-safety
我想知道 Python 内置容器(list、vector、set...)是否是线程安全的?还是我需要为我的共享变量实现锁定/解锁环境?
【问题讨论】:
标签: python thread-safety
您需要为所有将在 Python 中修改的共享变量实现自己的锁定。您不必担心从不会被修改的变量中读取(即并发读取是可以的),所以不可变类型(frozenset、tuple、str)可能是 em> 安全,但不会受到伤害。对于您将要更改的内容 - 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)
在 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.
【讨论】:
list1Lock)应该是共享>线程,以使其正常工作。两个独立的锁,每个线程一个,不会锁定任何东西,只会增加愚蠢的开销。
是的,当然你还是要小心
例如:
如果两个线程从只有一个项目的列表中竞争到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
【讨论】:
只要您不在线程的 C 代码中禁用 GIL,它们就是线程安全的。
【讨论】:
队列模块实现了多生产者、多消费者队列。当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。该模块中的 Queue 类实现了所有必需的锁定语义。
【讨论】: