睡觉的理发师,信号量?

时间:2013-05-24 10:40:02

标签: java multithreading semaphore

我一直试图解决这个问题两天了,我终于放弃了,我在这里发布我的代码,希望有些人可以为我提供我一直缺少的东西,因为我认为我是关闭,请帮忙!

理发师代码:

public Semaphore customer = new Semaphore(0);
public Semaphore barber = new Semaphore(0);
public Semaphore accessSeats = new Semaphore(1);
public int freeChairs = 5;

@Override
public void run() {
    while (true) {
        try {
            customer.acquire(); //it seems the barber never acuires a customer, even after the semaphore is released
            accessSeats.acquire();
            freeChairs += 1;
            cutHair();
            barber.release();
            accessSeats.release();
        } catch (InterruptedException ex){}

客户代码:

    public void run() {
    while (notCut) {
        try {
            bs.accessSeats.acquire();
        } catch (InterruptedException ex) {}
        if (bs.freeChairs > 0) {
            bs.freeChairs -= 1;
            bs.customer.release();
            bs.accessSeats.release();
            try {
                bs.barber.acquire(); //the customer cant get past this line
                getHaircut();
            } catch (InterruptedException ex) {}
        } else {
            bs.accessSeats.release();
            notCut = false;
        }
    }
}

我在随机计时器上创建了1个理发师和100个客户。

编辑:cutHair()在理发师的线程中休息1-5秒(随机)。并且getHaircut()只打印一条消息,然后设置notCut=false;

2 个答案:

答案 0 :(得分:0)

Semaphore是一个计数信号量 - 您应该阅读javadoc以获取更多信息。问题是,您永远不会告诉barber Semaphore有可用的Barber。所以永远不会允许Customer获得它。

解决方案: 当您创建Barber时,您要做的第一件事就是调用barber.release()(在while循环之前!)或用{1}初始化barber

答案 1 :(得分:0)

这不是一个正确的答案,但有几件事情在这里看起来不对:

1)freeChairs应该是AtomicInteger。

2)看起来你在错误的块中设置notCut = false - 肯定应该在getHaircut()之后设置? (尝试命名布尔'cut'并将其初始化为false。双阴性使得人类更难处理!)

3)很多信号量的获取和释放应该是相对于彼此的原子,但不是。例如

barber.release();
accessSeats.release();

看起来它应该是原子的 - 另一个线程应该永远不能看到已经释放理发信号量的状态但是accessSeats没有,但这不是这里的情况。这可能导致死锁,除非你非常小心你在不同的信号量上调用aquire / release的命令。