2010-09-07 18 views
1

Je voudrais placer deux objets dans une file d'attente, mais je dois m'assurer que les objets se trouvent dans les deux files d'attente en même temps, il ne faut donc pas les interrompre un bloc atomique. Est-ce que quelqu'un a une solution? Un grand merci ...Ajout d'objets à la file d'attente sans interruption

queue_01.put(car) 
queue_02.put(bike) 
+0

Le titre et le contenu de votre question sont contradictoires. S'il vous plaît soyez cohérent. Voulez-vous placer deux objets dans une file d'attente, ou deux objets dans deux files d'attente. Pourquoi vous souciez-vous de l'atome? Exécutez-vous du code multithread? – MattH

+0

Désolé, le titre est trompeur. Je veux écrire un objet dans une file d'attente et un autre objet dans une autre file (voir code). Et son code multi-threadé. –

Répondre

1

Vous pouvez utiliser un Condition object. Vous pouvez indiquer aux threads d'attendre cond.wait() et signaler que les files d'attente sont prêtes avec cond.notify_all(). Voir, par exemple, le merveilleux Python Module of the Week blog de Doug Hellman. Son code utilise multiprocessing; ici, je l'ai adapté pour threading:

import threading 
import Queue 
import time 

def stage_1(cond,q1,q2): 
    """perform first stage of work, then notify stage_2 to continue""" 
    with cond: 
     q1.put('car') 
     q2.put('bike') 
     print 'stage_1 done and ready for stage 2' 
     cond.notify_all() 
def stage_2(cond,q): 
    """wait for the condition telling us stage_1 is done""" 
    name=threading.current_thread().name 
    print 'Starting', name 
    with cond: 
     cond.wait() 
     print '%s running' % name 
def run(): 
    # http://www.doughellmann.com/PyMOTW/multiprocessing/communication.html#synchronizing-threads-with-a-condition-object 
    condition=threading.Condition() 
    queue_01=Queue.Queue() 
    queue_02=Queue.Queue()  
    s1=threading.Thread(name='s1', target=stage_1, args=(condition,queue_01,queue_02)) 
    s2_clients=[ 
     threading.Thread(name='stage_2[1]', target=stage_2, args=(condition,queue_01)), 
     threading.Thread(name='stage_2[2]', target=stage_2, args=(condition,queue_02)), 
     ] 
    # Notice stage2 processes are started before stage1 process, and yet they wait 
    # until stage1 finishes 
    for c in s2_clients: 
     c.start() 
     time.sleep(1) 
    s1.start() 
    s1.join() 
    for c in s2_clients: 
     c.join() 

run() 

L'exécution du script cède

Starting stage_2[1] 
Starting stage_2[2] 
stage_1 done and ready for stage 2 <-- Notice that stage2 is prevented from running until the queues have been packed. 
stage_2[2] running 
stage_2[1] running 
0

Pour atomiquement ajouter à deux files d'attente différentes, les serrures pour acquérir les deux files d'attente première. C'est plus facile à faire en créant une sous-classe de file d'attente qui utilise des verrous récursifs.

import Queue # Note: module renamed to "queue" in Python 3 
import threading 

class MyQueue(Queue.Queue): 
    "Make a queue that uses a recursive lock instead of a regular lock" 
    def __init__(self): 
     Queue.Queue.__init__(self) 
     self.mutex = threading.RLock() 

queue_01 = MyQueue() 
queue_02 = MyQueue() 

with queue_01.mutex: 
    with queue_02.mutex: 
     queue_01.put(1) 
     queue_02.put(2)