2012-06-19 2 views
5

У меня разные темы, и после обработки они помещают данные в общий список. Есть ли что-нибудь построенное в python для списка или массив numpy, к которому можно получить доступ только по одному потоку. Во-вторых, если это не тот элегантный способ сделать это?Как синхронизировать списки python?

ответ

4

threading предоставляет объекты Lock, если вам необходимо защитить весь критический раздел, или модуль Queue обеспечивает очередь, которая является потокобезопасной.

4

Согласно Thread synchronisation mechanisms in Python, чтение одного элемента из списка и изменение списка на месте гарантированно будут атомарными. Если это так (хотя, кажется, частично противоречит самому существованию модуля очереди), а затем, если ваш код все формы:

try: 
    val = mylist.pop() 
except IndexError: 
    # wait for a while or exit 
else: 
    # process val 

И все положить в mylist делается .append(), то ваш код уже потокобезопасен. Если вы не доверяете этому документу на этот счет, используйте queue.queue, который выполняет всю синхронизацию для вас, и имеет лучший API, чем list для параллельных программ - в частности, он дает вам возможность блокировки неограниченно или для таймаута , ожидая, что .pop() будет работать, если у вас нет чего-то другого, с которым поток может быть продолжен в среднем.

Для Numpy массивов, а в общем любом случае, если вам нужно больше, чем очереди производитель/потребитель, использовать Lock или RLock из threading - это реализовать протокол контекста менеджера, поэтому их использование довольно прост:

with mylock: 
    # Process as necessarry 

И python гарантирует, что блокировка будет выпущена после того, как вы упадете с конца блока with - в том числе в сложных случаях, например, если что-то делает рейз исключение.

Наконец, рассмотрим, подходит ли multiprocessing для вашего приложения, чем threading - потоки в Python не гарантируются на самом деле одновременно, а в CPython только при переходе на C-уровневый код. multiprocessing обошел эту проблему, но может иметь некоторые дополнительные накладные расходы - если вы еще этого не сделали, вы должны прочитать документы, чтобы определить, какой из них лучше подходит вашим потребностям.

+0

является 'mylist.pop (0)' также атмоическим? – willsteel

+0

Спасибо за 'с mylock:' напоминанием. Imho RLocks, используемые таким образом, часто являются наиболее четкой идиомой для защиты критических разделов в объектно-ориентированном программировании. – jjmontes

+0

@willsteel для окончательного ответа, я бы рекомендовал посмотреть исходный код Python на то, как реализованы списки, но я бы * представил *, что 'mylist.pop (0)' будет атомарным, если 'mylist.pop()' is (что я также не могу ответить окончательно, поэтому я также упоминаю другие методы синхронизации, а также может меняться в реализации Python). В частности, весь код C-уровня в CPython * может * быть защищен GIL (но имеет возможность его выпуска). 'pop' (возможно) либо выпускает GIL, либо нет, независимо от его аргумента. – lvc

Смежные вопросы