java.concurrent.Semaphore的意外行为

时间:2015-04-15 16:42:49

标签: java multithreading concurrency semaphore

我处于需要使用java.concurrent包中的Semaphore的情况,这样我就可以限制占用某个资源的线程数。以下是最基本的设置(代码):

    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

请注意,虽然我已经实例化了Semaphore的总并发线程数为2" new Semaphore(2);",这意味着一次只有2个线程可以访问特定资源,我可以找到全部4个线程:T1-T4已获得Semaphore许可(因此访问受限资源)。任何人都可以澄清我对java.concurrent.Semaphore的误解,因为我不期望输出:

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

据我所知,信号量无论如何都不能超过" 2"允许(对于此示例)可能正在等待的任意数量的线程。

1 个答案:

答案 0 :(得分:6)

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