信号量公平参数不是先进先出

时间:2017-07-11 10:20:02

标签: java multithreading concurrency semaphore java.util.concurrent

我正在开发一个简单的Semaphore程序,我正在初始化一个计数为4且开始6个线程的信号量。 在run方法中,我正在获取Semaphore锁,并且在每个线程完成后,我将释放锁。

这是我的代码:

import java.util.concurrent.Semaphore;

public class SemaphoreTest {

    static Semaphore semaphore = new Semaphore(4, true);

    static class MyThread extends Thread{

        String  name = "";

        public MyThread(String name){
            this.name = name;

        }

        public void run(){

            System.out.println(name+" going to acquire lock...");
            System.out.println("Available Permits = "+semaphore.availablePermits());

            try {
                semaphore.acquire();
                System.out.println(name+" got permit.");

                try{
                    for(int i=1;i<=1;i++){
                        System.out.println(name+" is performing operation "+i+". Available Semaphore permits are : "+semaphore.availablePermits());
                        Thread.sleep(1000);
                    }

                }finally{
                    System.out.println(name+" Releasing lock...");
                    semaphore.release();
                    System.out.println("Available permits after releasing "+"name"+" = "+semaphore.availablePermits());
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


        }
    }

    public static void main(String[] args){
        Thread t1 = new MyThread("A");
        t1.start();

        Thread t2 = new MyThread("B");
        t2.start();

        Thread t3 = new MyThread("C");
        t3.start();

        Thread t4 = new MyThread("D");
        t4.start();

        Thread t5 = new MyThread("E");
        t5.start();

        Thread t6 = new MyThread("F");
        t6.start();
    }

}

结果如下:

A going to acquire lock...
Available Permits = 4
C going to acquire lock...
A got permit.
A is performing operation 1. Available Semaphore permits are : 3
B going to acquire lock...
Available Permits = 3
B got permit.
F going to acquire lock...
E going to acquire lock...
Available Permits = 2
Available Permits = 3
D going to acquire lock...
Available Permits = 0
C got permit.
C is performing operation 1. Available Semaphore permits are : 0
E got permit.
E is performing operation 1. Available Semaphore permits are : 0
Available Permits = 2
B is performing operation 1. Available Semaphore permits are : 2
A Releasing lock...
E Releasing lock...
Available permits after releasing name = 2
D got permit.
D is performing operation 1. Available Semaphore permits are : 1
B Releasing lock...
C Releasing lock...
Available permits after releasing name = 1
F got permit.
F is performing operation 1. Available Semaphore permits are : 2
Available permits after releasing name = 2
Available permits after releasing name = 2
D Releasing lock...
F Releasing lock...
Available permits after releasing name = 3
Available permits after releasing name = 4

现在java文档:

  

java.util.concurrent.Semaphore.Semaphore(int permits,boolean fair)

     

使用给定的许可数和给定的公平性设置创建信号量。

     

参数:
  permits可用的初始许可数量。此值可能为负值,在这种情况下,必须在授予任何获取之前发布   fair如果此信号量将保证在争用中先进先出授权,则为真,否则为假

构造函数Semaphore(int permit,boolean fair)保证先进先出。但截至该计划的输出,它是不一样的。 锁定如下:

  

A - &gt; B - &gt; C - &gt; ë

锁定释放如下:

  

A - &gt; E - &gt; B - &gt; ç

请按照预期建议吗?或者有一些我想念的东西?

2 个答案:

答案 0 :(得分:2)

释放许可证的顺序仅仅是run方法花费的时间的结果,与公平无关。

这里的FIFO意味着如果两个线程调用semaphore.acquire()并且没有可用的许可,则首先调用它的线程将是第一个获得许可的线程。

在您的示例中,A,B,C,E获得许可,因为他们首先调用acquire - 而D和F必须等待许可才可用。然后似乎D在F之前调用acquire因此得到第一个可用的许可证。

答案 1 :(得分:0)

这里有一个关于线程时序的误解:你假设一旦线程输出消息它将获得锁定,但实际上没有理由不在这两个线程之间保持线程。

C: System.out.println(...);
C: thread gets put on hold
A: System.out.println(...);
A: aquires lock
B: System.out.println(...);
B: aquires lock
C: resumes
C: aquires lock