Семафор в Java
Семафор считает, сколько потоков одновременно
могут войти в участок. У Semaphore из
java.util.concurrent задают начальное число
разрешений в конструкторе.
Метод acquire() забирает одно разрешение и
при нуле блокирует поток. Метод release()
возвращает разрешение ожидающим. Снятие в
finally повторяет правило замка:
import java.util.concurrent.Semaphore;
class Hall {
private final Semaphore lane = new Semaphore(2);
private int inside = 0;
void visit() throws InterruptedException {
lane.acquire();
try {
inside++;
System.out.println(inside);
} finally {
inside--;
lane.release();
}
}
}
Два разрешения означают, что третий поток останется
ждать, пока кто-то не вызовет release().
Три задачи проходят короткий участок:
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args) throws InterruptedException {
Semaphore lane = new Semaphore(2);
Runnable pass = () -> {
try {
lane.acquire();
try {
System.out.println("start " + Thread.currentThread().getName());
Thread.sleep(50);
System.out.println("end " + Thread.currentThread().getName());
} finally {
lane.release();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};
Thread[] workers = {
new Thread(pass, "a"),
new Thread(pass, "b"),
new Thread(pass, "c"),
};
for (Thread worker : workers) {
worker.start();
}
for (Thread worker : workers) {
worker.join();
}
}
}
Семафор на 2 разрешения. Четыре потока
печатают метку входа, ждут 30 мс и
печатают выход, каждый раз забирая и возвращая
разрешение в finally.
Класс Booth с семафором на два места и
методом serve. Три запуска по очереди
вызывают обслуживание и выводят строку
"ok" внутри участка.