java.concurrent.Semaphore 的意外行为

Unexpected behavior of java.concurrent.Semaphore

我处于需要使用 java.concurrent 包中的信号量的情况,以便我可以限制占用特定资源的线程数。以下是最基本的设置(代码):

    package semaphor;

    import java.util.concurrent.Semaphore;

    /**
     * Created by NawazishMohammad on 15-04-2015.
     */
    public class SemaphoreTester {
       public static void main (String [] args){
           new Thread(new MyRunnable(), "T1").start();
           new Thread(new MyRunnable(), "T2").start();
           new Thread(new MyRunnable(), "T3").start();
           new Thread(new MyRunnable(), "T4").start();
       }
    }

    class MyRunnable implements Runnable{

        @Override
        public void run() {
            semaphoreStatus();
        }

        public void semaphoreStatus(){
            System.out.println("Thread waiting for permit: "+Thread.currentThread().getName());
            Semaphore sem = new Semaphore(2);
            try {
                sem.acquire();
                System.out.println("Thread got permit: " + Thread.currentThread().getName());
                System.out.println("Thread releasing permit: "+Thread.currentThread().getName());
                sem.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }

}

我得到以下输出

Thread waiting for permit: T1
Thread waiting for permit: T2
Thread waiting for permit: T3
Thread waiting for permit: T4
Thread got permit: T3
Thread got permit: T4
Thread got permit: T2
Thread got permit: T1
Thread releasing permit: T2
Thread releasing permit: T4
Thread releasing permit: T3
Thread releasing permit: T1

请注意,尽管我已经为两个“new Semaphore(2);”的总并发线程数实例化了信号量,这意味着一次只有 2 个线程可以访问特定资源,但我可以找到所有 4 个线程: T1-T4 已获得信号量许可(因此可以访问受限资源)。谁能澄清我对 java.concurrent.Semaphore 的误解(如果有的话),因为我不希望输出:

Thread got permit: T3
Thread got permit: T4
Thread got permit: T2
Thread got permit: T1 

我知道信号量在任何情况下都不能向可能正在等待的任意数量的线程提供超过“2”个许可(对于本例)。

您正在每个线程中创建一个新的信号量,这意味着每个线程将看到不同的信号量。不要在 semaphoreStatus() 内部调用 Semaphore sem = new Semaphore(2);,您应该在线程外部构造信号量,然后与它们共享。