'Do I understand threading.Condition correctly?
I was working on this leetcode problem (https://leetcode.com/problems/fizz-buzz-multithreaded/). I eventually found a slower answer and then looked at the faster ones and found this...
class FizzBuzz:
def __init__(self, n: int):
self.n = n
self.i = 1
self.lock = threading.Lock()
self.cond = threading.Condition(self.lock)
# printFizz() outputs "fizz"
def fizz(self, printFizz: 'Callable[[], None]') -> None:
while True:
with self.lock:
self.cond.wait_for(lambda: self.i > self.n or (self.i % 3 == 0 and self.i % 5 != 0))
if self.i > self.n:
break
printFizz()
self.i += 1
self.cond.notify_all()
# printBuzz() outputs "buzz"
def buzz(self, printBuzz: 'Callable[[], None]') -> None:
while True:
with self.lock:
self.cond.wait_for(lambda: self.i > self.n or (self.i % 3 != 0 and self.i % 5 == 0))
print("b a", self.i)
if self.i > self.n:
break
printBuzz()
self.i += 1
self.cond.notify_all()
# printFizzBuzz() outputs "fizzbuzz"
def fizzbuzz(self, printFizzBuzz: 'Callable[[], None]') -> None:
while True:
with self.lock:
self.cond.wait_for(lambda: self.i > self.n or (self.i % 3 == 0 and self.i % 5 == 0))
if self.i > self.n:
break
printFizzBuzz()
self.i += 1
self.cond.notify_all()
# printNumber(x) outputs "x", where x is an integer.
def number(self, printNumber: 'Callable[[int], None]') -> None:
while True:
with self.lock:
self.cond.wait_for(lambda: self.i > self.n or (self.i % 3 != 0 and self.i % 5 != 0))
if self.i > self.n:
break
printNumber(self.i)
self.i += 1
self.cond.notify_all()
I'm now trying to understand how threading.Condition.wait and threading.Condition.notify. This is what I think happens.
Each Condition is initialized with a reference to a threading.Lock. Two threads might use the same condition object or separate objects (with no effect on the below).
- The first thread calls
.wait. .waitchecks to make sure the lock has been acquired..waitsignals to the lock to release, and also that the condition is waiting on the lock.- The lock allows another thread to acquire it.
- Eventually the other thread calls
.notify. .notifysignals each condition that is waiting on the lock that the lock is about to be released and signal the lock to release.- The first thread calls
lock.acquire, which blocks temporarily. - The lock actually releases.
- The first thread's
lock.acquirereturns, unblocking that thread.
Is this correct?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
