public function acquire(): \Generator
    {
        $tsl = function () {
            // If there are no locks available or the wait queue is not empty,
            // we need to wait our turn to acquire a lock.
            if ($this->locks > 0) {
                --$this->locks;
                return false;
            }
            return true;
        };

        while ($this->locks < 1 || $this->synchronized($tsl)) {
            yield from Coroutine\sleep(self::LATENCY_TIMEOUT);
        }

        return new Lock(function () {
            $this->release();
        });
    }