Python threading.Event() - Ensuring all waiting threads wake up on event.set()

后端 未结 4 801
有刺的猬
有刺的猬 2021-02-05 19:20

I have a number of threads which wait on an event, perform some action, then wait on the event again. Another thread will trigger the event when it\'s appropriate.

I can

相关标签:
4条回答
  • 2021-02-05 20:02

    One solution I've used in the past is the Queue class for interthread communication. It is threadsafe and can be used to easy communication between threads when using both the multiprocessing and threading libraries. You could have the child threads waiting for something to enter the queue and then process the new entry. The Queue class also has a get() method which takes a handy blocking argument.

    0 讨论(0)
  • 2021-02-05 20:08

    If you want discrete, atomic events that can be processed sequentially by each thread, then do as krs1 & bot403 suggested and use a queue. The Python Queue class is synchronized - you do not have to worry about locking to use it.

    If however your needs are simpler (the event tells you that you have data available to read, etc), you can subscribe/register your threads as observers of an object responsible for triggering the events. This object would maintain the list of observer threading.Event objects. On a trigger, it can then call set() on all of the threading.Event objects in the list.

    0 讨论(0)
  • 2021-02-05 20:21

    You don't need an Event, and you don't need both a Lock and a Queue. All you need is a Queue.

    Call queue.put to drop a message in without waiting for it to be delivered or processed.

    Call queue.get in the worker thread to wait for a message to arrive.

    import threading
    import Queue
    
    active_queues = []
    
    class Worker(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.mailbox = Queue.Queue()
            active_queues.append(self.mailbox)
    
        def run(self):
            while True:
                data = self.mailbox.get()
                if data == 'shutdown':
                    print self, 'shutting down'
                    return
                print self, 'received a message:', data
    
        def stop(self):
            active_queues.remove(self.mailbox)
            self.mailbox.put("shutdown")
            self.join()
    
    
    def broadcast_event(data):
        for q in active_queues:
            q.put(data)
    
    t1 = Worker()
    t2 = Worker()
    t1.start()
    t2.start()
    broadcast_event("first event")
    broadcast_event("second event")
    broadcast_event("shutdown")
    
    t1.stop()
    t2.stop()
    

    The messages don't have to be strings; they can be any Python object.

    0 讨论(0)
  • 2021-02-05 20:21

    I'm not a python programmer but if an event can only be processed once perhaps you need to switch to a message queue with the appropriate locking so that when one thread wakes up and receives the event message it will process it and remove it from the queue so its not there if other threads wake up and look in the queue.

    0 讨论(0)
提交回复
热议问题