2011-12-18 27 views
7

Nie mogę zdecydować, czy następujący deque jest bezpieczny dla wątków.
W skrócie, utworzyłem klasę z deque, która wyświetla jej zawartość co 1 sekundę w nowym wątku (więc nie wstrzyma programu głównego podczas drukowania).
Deque jest wypełniony z głównego wątku, więc w zasadzie POWINNA być szansa na kolizję.
JEDNAK, deque jest wypełniana przy użyciu metody klasy, więc zasadniczo jest dostępna z poziomu samej instancji, a więc z tego samego wątku.
Oto uproszczony kod:Czy to jest bezpieczne w 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) 

Tak, chociaż dodawanie i usuwanie elementów z kolejki odbywać wewnątrz instancji, to istnieje ryzyko, ze względu na funkcję dodawania miano spoza instancji?

EDYTOWANIE:
Ponieważ potrzebuję zmodyfikować elementy w mojej deque, musiałem użyć Deque. To, co robię, to: roatować() do danego elementu, wyskakuj, zmodyfikuj, wepchnij z powrotem i obróć() z powrotem do pierwotnej pozycji.
ile znajdę sposób wdrażania elementów modyfikujących w kolejce, muszę trzymać się deque

+2

Jeśli wystarczy kolejki wątku bezpieczny (nie do zobaczenia przy użyciu jakichkolwiek funkcji specyficznych dla paczki), prawdopodobnie powinieneś użyć wbudowanej kolejki wątkowej bezpiecznej (http://docs.python.org/library/queue.html). – delnan

+0

David, dzięki, dodałem pętlę. Delnan, Wykluczyłem niektóre funkcje. Deque jest obracany co jakiś czas, dzięki czemu przedmioty mogą być wyskakiwane, modyfikowane, popychane z powrotem i obracane z powrotem do swojej pierwotnej pozycji. Nie znalazłem sposobu na zrobienie tego z Queue – user1102018

+6

Nie można napisać kodu, aby przetestować, czy coś jest bezpieczne dla wątków, a zamiast tego musisz przeczytać dokumentację lub zapoznać się z kodem źródłowym. Często, jeśli coś nie jest bezpieczne dla wątków, nadal będzie działało prawie cały czas w kontekście wątków, a następnie eksploduje kilka tygodni później. –

Odpowiedz

13

deque jest thread-safe (http://docs.python.org/library/collections.html#deque-objects) dla Dołącza i wyskakuje z przeciwnych stron. Beneath here, docs tylko wspomnieć, że append() i popleft() są wątkowo bezpieczne.

Istnieje kolejna implementacja samej kolejki. Powinieneś go używać, chyba że masz jakieś dziwne wymagania.

+4

Jest nie tylko bezpieczna dla wątków, ale jej wydajność jest znacznie wyższa niż modułu Kolejka.Cenną rzeczą dodawaną przez moduł kolejki jest to, że 'get' może blokować. – amcnabb

+0

Tylko wątek bezpieczny dołącza i wyskakuje jak go czytam (na przykład, nie możesz koniecznie użyć 'len()' przez wątki?) –

+0

Deque zdecydowanie rzuca, jeśli robisz iterację i pchasz w tym samym czasie – Brannon

2

Więcej informacji znajduje się odwoływać za bilet Python deque wątku bezpieczeństwa (https://bugs.python.org/issue15329).

Tytuł "wyjaśnienie, jakie deque metody są thread-safe", dolna linia:

dołączyć deque jest(), appendleft(), pop(), popleft() i len (d) operacje są wątkowo bezpieczne w CPython. Metody Append mają DECREF na końcu (w przypadkach, gdy maxlen zostało ustawione), ale to dzieje się po wszystkich zmianach struktury zostały dokonane i niezmienniki zostały przywrócone, więc jest w porządku, aby traktować te operacje jako atomowy.

W każdym razie, jeśli nie jesteś w 100% pewien i wolisz niezawodność nad wydajności, wystarczy umieścić jak Lock na print self.q.popleft() i self.q.append(val);)

Powiązane problemy