Java公平信号量

时间:2016-08-15 12:47:55

标签: java multithreading semaphore

我正在尝试理解这个旧考试任务的答案,其中学生应该使用javas reentrantlock实现公平的二进制信号量。我不明白这些柜台的重点:

int next = 0;
int nextToGo = 0;
int myNumber; 

它在任务描述中说“您可以假设程序中最多有20个线程使用信号量。此外,在一次运行程序期间最多将执行1000万个信号量操作。 “ 在任务的解决方案中,它说:“每个尝试获取信号量的线程必须在队列中注册,并且只有在之前的线程离开之后才离开队列。每个线程都记住它在队列中的位置使用32-计数器将不会回转,因为在信号量上将执行大多数1000万次操作,但即使计数器可以包围“。

,代码也能正常工作。”

对我而言,老师似乎忽略了解决方案中1000万个线程的限制,但我的主要问题是为什么在将线程放入lock()和await()语句的队列中时需要计数器,并且有一个正在检查的自由变量。并且ReentrantLock(true)不会照顾公平吗?

解决方案:

public class FairSemaphore {

    ReentrantLock l = new ReentrantLock(true);
    Condition c = l.newCondition();
    int next = 0;
    int nextToGo = 0;
    boolean free = true;

    public void aqcuire() throws InterruptedException {
            l.lock();
            int myNumber = next++; 

            while(!(free && myNumber == nextToGo)) {
                    c.await();
            }
            free = false;
            nextToGo++;
            l.unlock();
    }

    public void release() {
            l.lock();
            free = true;
            c.signalAll();
            l.unlock();     
    }
}

1 个答案:

答案 0 :(得分:5)

虽然您可能会认为ReentrantLock上的线程阻塞 排队,不能保证队列作为FIFO公平行事 队列。文档明确告诉您:

  

...此锁不保证任何特定访问权限   订购。    但是请注意,锁的公平性并不能保证线程调度的公平性。 ...

阅读整个docs,即使您创建了一个公平的ReentrantLock,它也不会保证它是公平的。

然而,显示的代码确实表现得很公平,因为计数器使线程以FIFO顺序获取锁定。

代码是一个Ticket Lock,所以也请查看https://en.wikipedia.org/wiki/Ticket_lock