Являются ли встроенные контейнеры Python поточно-ориентированными? - PullRequest
48 голосов
/ 09 февраля 2010

Я хотел бы знать, являются ли встроенные контейнеры Python (list, vector, set ...) потокобезопасными? Или мне нужно реализовать среду блокировки / разблокировки для моей общей переменной?

Ответы [ 3 ]

43 голосов
/ 09 февраля 2010

Вам необходимо реализовать собственную блокировку для всех общих переменных, которые будут изменены в Python. Вам не нужно беспокоиться о чтении из переменных, которые не будут изменены (т. Е. Одновременное чтение нормально), поэтому неизменяемые типы (frozenset, tuple, str): , вероятно, * 1005. * безопасно, но это не повредит. Для вещей, которые вы собираетесь изменять - 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 и более ранних версиях его нет, поэтому вы захотите поместить вызовы acqu () / 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)

Немного полезной информации о синхронизации потоков в Python .

8 голосов
/ 09 февраля 2010

Да, но вы все равно должны быть осторожны, конечно

Например:

Если две нити стремятся к 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
4 голосов
/ 09 февраля 2010

Они являются поточно-ориентированными, если вы не отключите GIL в C-коде для потока.

...