Двоичный семафор не работает, если 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,

Другие вопросы по тегам