Gymterview
senior

Напишите минимальный неблокирующий стек (всего два метода — push() и pop()) с использованием Semaphore

Стек с использованием Semaphore для управления доступом. Строго говоря, это блокирующий стек (семафор блокирует поток при захвате), а не lock-free, но он демонстрирует использование Semaphore как мьютекса (с одним permit).

Код: стек на Semaphore
class SemaphoreStack<T> {
    private final Semaphore semaphore = new Semaphore(1);
    private Node<T> head = null;

    SemaphoreStack<T> push(T value) {
        semaphore.acquireUninterruptibly();
        try {
            head = new Node<>(value, head);
        } finally {
            semaphore.release();
        }
        return this;
    }

    T pop() {
        semaphore.acquireUninterruptibly();
        try {
            Node<T> current = head;
            if (current != null) {
                head = head.next;
                return current.value;
            }
            return null;
        } finally {
            semaphore.release();
        }
    }

    private static class Node<E> {
        private final E value;
        private final Node<E> next;

        private Node(E value, Node<E> next) {
            this.value = value;
            this.next = next;
        }
    }
}

Отличие от lock-free версии: здесь Semaphore с одним permit используется как мьютекс — только один поток может одновременно выполнять push() или pop(). В lock-free версии потоки не блокируют друг друга, а используют CAS-цикл.

На собеседовании стоит отметить, что Semaphore(1) — это не то же самое, что ReentrantLock: семафор не реентрабельный, и release() может вызвать любой поток. Также acquireUninterruptibly() выбран намеренно — он не бросает InterruptedException, упрощая API.