implemented with Semaphore