1115. Print FooBar Alternately - cocoder39/coco39_LC GitHub Wiki
1115. Print FooBar Alternately
Option 1: condition
from threading import Condition
class FooBar:
def __init__(self, n):
self.n = n
self.condition = Condition()
self.count = 0
def foo(self, printFoo: 'Callable[[], None]') -> None:
for i in range(self.n):
with self.condition:
self.condition.wait_for(lambda: 2*i == self.count)
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.count += 1
self.condition.notifyAll()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
with self.condition:
self.condition.wait_for(lambda: 2*i+1 == self.count)
# printBar() outputs "bar". Do not change or remove this line.
printBar()
self.count += 1
self.condition.notifyAll()
Option 2: event
from threading import Event
class FooBar:
def __init__(self, n):
self.n = n
self.foo_event = Event()
self.bar_event = Event()
self.foo_event.set()
def foo(self, printFoo: 'Callable[[], None]') -> None:
for i in range(self.n):
self.foo_event.wait()
self.foo_event.clear()
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.bar_event.set()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
self.bar_event.wait()
self.bar_event.clear()
# printBar() outputs "bar". Do not change or remove this line.
printBar()
self.foo_event.set()
Option 3: semaphore
from threading import Semaphore
class FooBar:
def __init__(self, n):
self.n = n
self.foo_event = Semaphore(1)
self.bar_event = Semaphore(0)
def foo(self, printFoo: 'Callable[[], None]') -> None:
for i in range(self.n):
self.foo_event.acquire()
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.bar_event.release()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
self.bar_event.acquire()
# printBar() outputs "bar". Do not change or remove this line.
printBar()
self.foo_event.release()
Option 4: lock
from threading import Lock
class FooBar:
def __init__(self, n):
self.n = n
self.foo_event = Lock()
self.bar_event = Lock()
self.bar_event.acquire()
def foo(self, printFoo: 'Callable[[], None]') -> None:
for i in range(self.n):
self.foo_event.acquire()
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.bar_event.release()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
self.bar_event.acquire()
# printBar() outputs "bar". Do not change or remove this line.
printBar()
self.foo_event.release()
Option 5: barrier
This solution can pass OJ but doesn't guarantee order between foo and bar in theory
EG. pint foo -> foo calls wait -> bar calls wait -> print foo -> print bar
from threading import Barrier
class FooBar:
def __init__(self, n):
self.n = n
self.barrier = Barrier(2)
def foo(self, printFoo: 'Callable[[], None]') -> None:
for i in range(self.n):
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.barrier.wait()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
self.barrier.wait()
# printBar() outputs "bar". Do not change or remove this line.
printBar()
Option 6: barrier
This solution can pass OJ but doesn't guarantee order between foo and bar in theory
print foo -> foo calls bar_wait -> bar calls foo wait -> foo calls foo wait -> print foo
from threading import Barrier
class FooBar:
def __init__(self, n):
self.n = n
self.foo_barrier = Barrier(2)
self.bar_barrier = Barrier(2)
def foo(self, printFoo: 'Callable[[], None]') -> None:
for i in range(self.n):
self.foo_barrier.wait()
# printFoo() outputs "foo". Do not change or remove this line.
printFoo()
self.bar_barrier.wait()
def bar(self, printBar: 'Callable[[], None]') -> None:
for i in range(self.n):
self.foo_barrier.wait()
self.bar_barrier.wait()
# printBar() outputs "bar". Do not change or remove this line.
printBar()