Двоичный семафор не работает, если release() предшествует acqu ()
Я пишу тестовый код, где я нашел, если мы положим release()
до acquire()
тогда функциональность двоичного семафора нарушена.
Я проверил и нашел более одного потока проходит acquire()
и увеличить счетчик до N, где N - количество потоков, что противоречит двоичному семафору.
import java.util.concurrent.Semaphore;
/**
* Consider an ATM cubicle with 1 ATM, Semaphore can make sure only 1 person
* can access simultaneously.
*
* Here if relese() comes before then this binary semaphore is not working.
*/
public class SemaphoreTest {
// max 4 people
static Semaphore semaphore = new Semaphore(1);
public static void main(String[] args) {
System.out.println("Total available Semaphore permits : " + semaphore.availablePermits());
MyATMThread t1 = new MyATMThread("A",semaphore);
t1.start();
MyATMThread t2 = new MyATMThread("B",semaphore);
t2.start();
MyATMThread t3 = new MyATMThread("C",semaphore);
t3.start();
MyATMThread t4 = new MyATMThread("D",semaphore);
t4.start();
MyATMThread t5 = new MyATMThread("E",semaphore);
t5.start();
MyATMThread t6 = new MyATMThread("F",semaphore);
t6.start();
}
}
class MyATMThread extends Thread {
String name = "";
Semaphore semaphore = null;
MyATMThread(String name,Semaphore s) {
this.name = name;
this.semaphore=s;
}
public void run() {
try {
System.out.println(name + " : acquiring lock...");
System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits());
semaphore.release();
semaphore.acquire();
System.out.println(name + " : got the permit!");
try {
for (int i = 1; i <= 5; i++) {
System.out.println(name + " : is performing operation " + i + ", available Semaphore permits : "
+ semaphore.availablePermits());
// sleep 1 second
Thread.sleep(1000);
}
} finally {
// calling release() after a successful acquire()
System.out.println(name + " : releasing lock...");
semaphore.release();
System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Кто-нибудь может объяснить это поведение?
3 ответа
Да, вы пишете неработающий код (по крайней мере, в соответствии с вашими ожиданиями), выпуская (увеличивая разрешения) перед приобретением. Это совершенно верно, но если вы намереваетесь иметь одно разрешение, вам не следует увеличивать его, вызывая release()
до acquire()
,
Semaphore
позволяет увеличить количество разрешений сверх того, что было указано в качестве первоначальной суммы. Это может быть использовано, например, для дросселирования. Рабочие темы будут делать acquire()/release()
и регулятор будет уменьшать / увеличивать разрешения в зависимости от некоторой логики.
Метод release() используется для увеличения разрешений, поскольку из документов:
Не требуется, чтобы поток, который выпускает разрешение, получил это разрешение, вызвав функцию acqu. Правильное использование семафора устанавливается соглашением о программировании в приложении.
Другими словами:
semaphore.release (10), добавит еще 10 разрешений к текущим разрешениям
Вы можете думать о release()
как "создание" другого разрешения, если этот поток ранее не получил разрешение от этого Semaphore
,