2

All existing examples of threading.Condition and threading.Event present in internet are to solve producer consumer issue. But this can be done using either of them. Only advantage of Condition I have found is - it supports two types of notify function (notify and notifyAll)

Here I have easily replicated an existing example of Condition to Event. the Condition example is taken from here

Example using Condition:

def consumer(cv):
    logging.debug('Consumer thread started ...')
    with cv:
        logging.debug('Consumer waiting ...')
        cv.wait()
        logging.debug('Consumer consumed the resource')

def producer(cv):
    logging.debug('Producer thread started ...')
    with cv:
        logging.debug('Making resource available')
        logging.debug('Notifying to all consumers')
        cv.notifyAll()

if __name__ == '__main__':
    condition = threading.Condition()
    cs1 = threading.Thread(name='consumer1', target=consumer, args=(condition,))
    cs2 = threading.Thread(name='consumer2', target=consumer, args=(condition,))
    pd = threading.Thread(name='producer', target=producer, args=(condition,))

    cs1.start()
    time.sleep(2)
    cs2.start()
    time.sleep(2)
    pd.start()

Example using Event:

def consumer(ev):
    logging.debug('Consumer thread started ...')
    logging.debug('Consumer waiting ...')
    ev.wait()
    logging.debug('Consumer consumed the resource')

def producer(ev):
    logging.debug('Producer thread started ...')
    logging.debug('Making resource available')
    logging.debug('Notifying to all consumers')
    ev.set()

if __name__ == '__main__':
    event = threading.Event()
    cs1 = threading.Thread(name='consumer1', target=consumer, args=(event,))
    cs2 = threading.Thread(name='consumer2', target=consumer, args=(event,))
    pd = threading.Thread(name='producer', target=producer, args=(event,))

    cs1.start()
    time.sleep(2)
    cs2.start()
    time.sleep(2)
    pd.start()

Output:

(consumer1) Consumer thread started ...
(consumer1) Consumer waiting ...
(consumer2) Consumer thread started ...
(consumer2) Consumer waiting ...
(producer ) Producer thread started ...
(producer ) Making resource available
(producer ) Notifying to all consumers
(consumer1) Consumer consumed the resource
(consumer2) Consumer consumed the resource

Can someone give an example which is possible by using Condition but not by Event?

  • "it supports two types of notify function" That's basically it, plus the locking your code uses as well. What more do you need than this? – MisterMiyagi Jun 26 '22 at 11:40
  • Does this answer your question? [threading.Condition vs threading.Event](https://stackoverflow.com/questions/7424590/threading-condition-vs-threading-event) – MisterMiyagi Jun 26 '22 at 11:42
  • Here context manager of Condition object does not seem to be locking properly. As First customer is waiting within the lock, how can the second cursomer thread enter the same block at the same time? – Saumya Sengupta Jun 26 '22 at 12:47

1 Answers1

3

Event has state: You can call e.is_set() to find out whether e has been set() or clear()ed.

A Condition has no state. If some thread happens to call c.notify() or c.notify_all() when other threads are waiting in c.wait(), then one or more of those other threads will be awakened. But if the notification comes at a moment when no other thread is waiting, then c.notify() and c.notify_all() do absolutely nothing at all.

In short: An Event is a complete communication mechanism that can be use to transmit information from one thread to another. But a Condition cannot, by itself, be reliably used for communication. It has to be incorporated into some larger scheme.


IMO: Both classes are poorly named. A better name for Event would be Bit because it stores one bit of information.

A better name for Condition would be Event. Notifying a condition is an "event" it the true sense of the word. If you happen to be watching for it at the moment when it happens, then you learn something. But if you don't happen to be watching, then you miss it altogether.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • It answers me partially. Condition has method named wait_for which waits until a functional condition evaluates to True. Most probably that is the main reason of naming this class as Condition. But I agree with your comment - "Both classes are poorly named". – Saumya Sengupta Jun 26 '22 at 17:20
  • @SaumyaSengupta, I forgot that Python's `Condition` class has `wait_for(...)`. C++ `std::condition` has something similar. Those are recent additions to the basic idea of a "condition variable," and I am old-school (retired after 45 years of developing software.) They make it easier to use `Condition` objects by letting you write a single line of code that loops, testing shared variables for the _real_ condition that your program is awaiting. But unlike the case with the `Event` class, you still need those other shared variables to hold the state that you're looking for. – Solomon Slow Jun 26 '22 at 17:59