2011-12-18 5 views
7

Я не могу решить, является ли следующий deque потокобезопасным.
Короче говоря, я создал класс с deque, который отображает его содержимое каждые 1 секунду в новом потоке (так что во время печати он не приостанавливает основную программу).
Дека заполняется из основной нити, поэтому в основном там ДОЛЖЕН быть шанс столкновения.
ОДНАКО, deque заполняется с использованием метода класса, поэтому по существу он доступен изнутри самого экземпляра, поэтому из той же нити.
Вот упрощенный код:Является ли этот deque потокобезопасным в python?

import threading 
import time 
from collections import deque 

class MyQueue(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     self.q = deque() 
     self.start() 

    def run(self): 
     # pop out queue items every 1 sec 
     # (please ignore empty deque for now) 
     while True: 
      print self.q.popleft() 
      time.sleep(1) 

    def add_to_q(self, val): 
     # this function is called from outside 
     self.q.append(val) 

# main 
# fill the queue with values 
qu = MyQueue() 
for i in range(1:100): 
    qu.add_to_q(i) 

Таким образом, хотя добавление и удаление элементов из очереди происходят внутри экземпляра, есть риск, связанный с функцией добавления вызывается извне экземпляра?

EDIT:
Поскольку мне нужно изменить элементы в моем deque, мне пришлось использовать Deque. То, что я делаю, это: roatate() для данного элемента, вытащить его, изменить, вставить обратно и повернуть() обратно в исходное положение.
Если я не найду способ реализации модифицирующих элементов в очереди, я должен буду придерживаться Deque

+2

Если вам просто нужно поточно-очередь (я не если вы используете какие-либо функции, связанные с deque), вы, вероятно, должны использовать [встроенную потокобезопасную очередь] (http://docs.python.org/library/queue.html). – delnan

+0

Дэвид, спасибо, я добавил петлю. delnan, я исключил некоторые функции. Время разворачивается, поэтому предметы можно выталкивать, модифицировать, отталкивать назад и поворачивать обратно в исходное положение. Я не нашел способ сделать это с помощью Queue – user1102018

+6

Невозможно написать код для проверки, если что-то потокобезопасно, и вместо этого вам нужно прочитать документацию или изучить исходный код. Часто, если что-то не потокобезопасно, оно все равно будет работать почти все время в поточном контексте, а затем взорваться через несколько недель. –

ответ

13

Deque потокобезопасно (http://docs.python.org/library/collections.html#deque-objects) для добавляет или выскакивает с противоположных сторон. Beneath here, в документах упоминается только то, что append() и popleft() являются потокобезопасными.

Существует поточная реализация самой очереди. Поэтому вы должны использовать его, если у вас нет странных требований.

+4

Не только deque threadsafe, но и производительность намного выше, чем модуль Queue.Ценная вещь, добавляемая модулем Queue, заключается в том, что 'get' может блокироваться. – amcnabb

+0

Только потокобезопасное приложение добавляет и выскакивает, когда я его читаю (например, вы не можете использовать 'len()' через потоки, не так ли?) –

+0

deque определенно выбрасывает, если вы повторяете и толкаете одновременно – Brannon

2

Для получения информации есть билет на Python ссылаются на DEQUE безопасности потоков (https://bugs.python.org/issue15329).

Название "выяснить, какие Deque методы являются поточно-", нижняя линия:

добавьте Deque (в), appendleft(), поп(), popleft() и LEN (д) операции являются поточно-безопасными в CPython. Прикладные методы имеют DECREF в конце (для случаев, когда maxlen был установлен), но этот происходит после того, как были сделаны все обновления структуры, и были восстановлены инварианты , поэтому нормально обрабатывать эти операции как атомный.

Во всяком случае, если вы не уверены на 100%, и вы предпочитаете надежность по сравнению с производительностью, просто поставить как замок для print self.q.popleft() и self.q.append(val);)

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