2010-09-07 26 views
1

我想將兩個對象放入隊列中,但我必須確保對象同時處於兩個隊列中,因此不應該在兩者之間中斷 - 類似一個原子塊。有人有解決方案嗎?非常感謝...在不中斷的情況下將對象添加到隊列中

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

問題的標題和內容是矛盾的。請保持一致。你想把兩個對象放在一個隊列中,還是兩個對象放在兩個隊列中。你爲什麼關心原子?你是否運行多線程代碼? – MattH 2010-09-07 12:12:51

+0

對不起,標題有誤導性。我想將一個對象寫入一個隊列,將另一個對象寫入另一個隊列(請參閱代碼)。和它的多線程代碼。 – 2010-09-07 12:35:43

回答

1

您可以使用Condition object。您可以告訴線程等待cond.wait(),並在隊列準備就緒時發出信號cond.notify_all()。例如,請參閱Doug Hellman的精彩Python Module of the Week blog。他的代碼使用multiprocessing;在這裏,我已經適應它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() 

運行腳本產生

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

以原子添加到兩個不同的隊列,獲取鎖兩個隊列第一位。通過使用遞歸鎖定的Queue的子類最容易做到這一點。

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) 
相關問題