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

时间:2020-12-26 18:09:36

I would like to know if the Python built-in containers (list, vector, set...) are thread-safe? Or do I need to implement a locking/unlocking environment for my shared variable?

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

3 个解决方案

#1


41  

You need to implement your own locking for all shared variables that will be modified in Python. You don't have to worry about reading from the variables that won't be modified (ie, concurrent reads are ok), so immutable types (frozenset, tuple, str) are probably safe, but it wouldn't hurt. For things you're going to be changing - list, set, dict, and most other objects, you should have your own locking mechanism (while in-place operations are ok on most of these, threads can lead to super-nasty bugs - you might as well implement locking, it's pretty easy).

您需要为将在Python中修改的所有共享变量实现自己的锁定。您不必担心从不会被修改的变量中读取(即并发读取是可以的),因此不可变类型(frozenset,tuple,str)可能是安全的,但它不会受到伤害。对于你将要改变的事情 - 列表,集合,字典和大多数其他对象,你应该有自己的锁定机制(虽然就地操作在大多数情况下都可以,线程可能导致超级恶劣的错误 - 你可以实现锁定,这很简单)。

By the way, I don't know if you know this, but locking is very easy in Python - create a threading.lock object, and then you can acquire/release it like this:

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

In Python 2.5, do from __future__ import with_statement; Python 2.4 and before don't have this, so you'll want to put the acquire()/release() calls in try:...finally: blocks:

在Python 2.5中,从__future__ import with_statement; Python 2.4和之前没有这个,所以你要把gets()/ release()调用放在try:... finally:blocks:

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.

关于Python中线程同步的一些非常好的信息。

#2


8  

Yes, but you still need to be careful of course

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

For example:

例如:

If two threads are racing to pop() from a list with only one item, One thread will get the item successfully and the other will get an IndexError

如果两个线程从仅包含一个项目的列表中竞争pop(),则一个线程将成功获取该项目,另一个线程将获得一个IndexError

Code like this is not thread-safe

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

if L:
    item=L.pop() # L might be empty by the time this line gets executed

You should write it like this

你应该这样写

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

#3


4  

They are thread-safe as long as you don't disable the GIL in C code for the thread.

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

#1


41  

You need to implement your own locking for all shared variables that will be modified in Python. You don't have to worry about reading from the variables that won't be modified (ie, concurrent reads are ok), so immutable types (frozenset, tuple, str) are probably safe, but it wouldn't hurt. For things you're going to be changing - list, set, dict, and most other objects, you should have your own locking mechanism (while in-place operations are ok on most of these, threads can lead to super-nasty bugs - you might as well implement locking, it's pretty easy).

您需要为将在Python中修改的所有共享变量实现自己的锁定。您不必担心从不会被修改的变量中读取(即并发读取是可以的),因此不可变类型(frozenset,tuple,str)可能是安全的,但它不会受到伤害。对于你将要改变的事情 - 列表,集合,字典和大多数其他对象,你应该有自己的锁定机制(虽然就地操作在大多数情况下都可以,线程可能导致超级恶劣的错误 - 你可以实现锁定,这很简单)。

By the way, I don't know if you know this, but locking is very easy in Python - create a threading.lock object, and then you can acquire/release it like this:

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

In Python 2.5, do from __future__ import with_statement; Python 2.4 and before don't have this, so you'll want to put the acquire()/release() calls in try:...finally: blocks:

在Python 2.5中,从__future__ import with_statement; Python 2.4和之前没有这个,所以你要把gets()/ release()调用放在try:... finally:blocks:

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.

关于Python中线程同步的一些非常好的信息。

#2


8  

Yes, but you still need to be careful of course

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

For example:

例如:

If two threads are racing to pop() from a list with only one item, One thread will get the item successfully and the other will get an IndexError

如果两个线程从仅包含一个项目的列表中竞争pop(),则一个线程将成功获取该项目,另一个线程将获得一个IndexError

Code like this is not thread-safe

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

if L:
    item=L.pop() # L might be empty by the time this line gets executed

You should write it like this

你应该这样写

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

#3


4  

They are thread-safe as long as you don't disable the GIL in C code for the thread.

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