48-ms Python solution, beats 97%
The idea is that there are three threading.Lock objects, one for each of the methods zero(), even() and odd(), as well as an auxiliary variable self.i which ind
The idea is that there are three [`threading.Lock`](https://docs.python.org/3/library/threading.html#lock-objects) objects, one for each of the methods `zero()`, `even()` and `odd()`, as well as an auxiliary variable `self.i` which indicates the last number that was printed (not including the zeros printed by `zero()`). \n\nInitially, locks for `even()` and `odd()` are acquired to prevent them from running. When `zero()` runs, if `self.i` is even (odd), the lock for odd (even) is released, and when either `odd()` or `even()` runs, the lock for `zero()` is released.\n\n```python\nimport threading\nfrom typing import Callable, Optional\n\n\nclass ZeroEvenOdd:\n    def __init__(self, n: int):\n        self.n = n\n        self.i = 0\n\n        self.lock_zero = threading.Lock()\n        self.lock_odd = threading.Lock()\n        self.lock_even = threading.Lock()\n\n        self.lock_odd.acquire()\n        self.lock_even.acquire()\n\n    def zero(self, printNumber: Callable[[int], None]) -> None:\n        for _ in range(self.n):\n            self.lock_zero.acquire()\n            printNumber(0)\n\n            if self.i % 2 == 0:\n                self.lock_odd.release()\n            else:\n                self.lock_even.release()\n\n    def even(self, printNumber: Callable[[int], None]) -> None:\n        for i in range(2, self.n + 1, 2):\n            self.lock_even.acquire()\n            printNumber(i)\n            self.i = i\n            self.lock_zero.release()\n\n    def odd(self, printNumber: Callable[[int], None]) -> None:\n        for i in range(1, self.n + 1, 2):\n            self.lock_odd.acquire()\n            printNumber(i)\n            self.i = i\n            self.lock_zero.release()
[]