信号量的大小可以与线程的执行顺序相关吗?

时间:2013-05-30 13:09:54

标签: java concurrency semaphore

查看1Z0-804考试的一些文献,我找到了这个例子的问题:

  

请考虑以下计划:

class ATMRoom {
    public static void main(String []args) {
        Semaphore machines = new Semaphore(2); //#1
        new Person(machines, "Mickey");
        new Person(machines, "Donald");
        new Person(machines, "Tom");
        new Person(machines, "Jerry");
        new Person(machines, "Casper");
    }
}

class Person extends Thread {
    private Semaphore machines;
    public Person(Semaphore machines, String name) {
        this.machines = machines;
        this.setName(name);
        this.start();
    }
    public void run() {
        try {
            System.out.println(getName()
                + " waiting to access an ATM machine");
                machines.acquire();
            System.out.println(getName()
                + " is accessing an ATM machine");
            Thread.sleep(1000);
            System.out.println(getName()
                + " is done using the ATM machine");
            machines.release();
        } catch(InterruptedException ie) {
            System.err.println(ie);
        }
    }
}
  

如果用以下语句替换语句#1,那么哪一个选项是正确的? Semaphore machines = new Semaphore(2, true);

     

省略答案

正确答案的解释引起了我的注意:

  

第二个参数表示信号量对象的公平性策略。但是,那里   是信号量对象的两个许可证;所以你无法预测等待的顺序   人们将获得访问ATM的许可。

我会说,由于线程的非确定性,不能预测顺序,不是因为信号量中的许可数量,而且公平参数保证等待线程以相同的顺序被唤醒他们获得了信号量,但收购订单仍无法确定。我的解释是否正确?

2 个答案:

答案 0 :(得分:1)

据我了解,是的,你的想法是正确的,因为公平的信号量使用FairSync,并且'获取机制不会在可用许可数量上中继,而只在线程队列中的第一个线程上继续:

        protected int tryAcquireShared(int acquires) {
        for (;;) {
            if (getFirstQueuedThread() != Thread.currentThread() &&
                hasQueuedThreads())
                return -1;
         ....

答案 1 :(得分:0)

我会说,因为他们都在他们的构造函数中调用start,你只能保证创建线程的顺序和开始顺序,你不能说他们run的顺序方法被调用。

所以 - 基本上 - 你是对的,信号量的数量根本不在订单中。