Добавление объектов в очередь без перерыва - PullRequest
1 голос
/ 07 сентября 2010

Я хотел бы поместить два объекта в очередь, но я должен быть уверен, что объекты находятся в обеих очередях одновременно, поэтому он не должен прерываться между ними - что-то вроде атомарного блока.У кого-нибудь есть решение?Большое спасибо ...

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

Ответы [ 2 ]

1 голос
/ 07 сентября 2010

Вы можете использовать Объект условия . Вы можете указать потокам ждать с cond.wait() и сообщить, когда очереди готовы с cond.notify_all(). См., Например, замечательный модуль Python модуля недели Дуга Хеллмана Его код использует 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 голосов
/ 07 сентября 2010

Чтобы атомарно добавить в две разные очереди, сначала получите блокировки для обеих очередей.Это проще всего сделать, создав подкласс 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...