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.