0

我正在编写一个测试代码,我发现如果我们在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();

        }

    }

}

有人可以解释这种行为吗?

4

3 回答 3

3

是的,您在获取之前通过发布(增加许可)来编写损坏的代码(至少按照您的期望)。这是完全有效的,但如果您打算拥有一个许可证,则不应通过调用release()before来增加它们acquire()

Semaphore允许您增加超出初始数量的许可。这可以用于例如节流。工作线程将执行此操作acquire()/release(),并且限制器将根据某些逻辑减少/增加许可。

于 2017-03-30T09:20:42.643 回答
2

release() 方法用于增加许可,因为来自文档:

不要求释放许可的线程必须通过调用acquire获得该许可。信号量的正确使用是通过应用程序中的编程约定建立的。

换句话说:

semaphore.release(10), 将在当前许可的基础上再增加 10 个许可

于 2017-03-30T09:36:57.107 回答
0

release()如果该线程之前没有从该线程获得许可,您可以将其视为“创建”另一个许可Semaphore

于 2017-03-30T09:37:35.973 回答