【问题标题】:Sleeping barber, semaphores?睡觉的理发师,信号灯?
【发布时间】:2013-05-24 10:40:02
【问题描述】:

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

理发师代码:

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;

【问题讨论】:

  • 您看到任何异常吗?看起来你只是在捕捉异常。至少打印堆栈跟踪。
  • 我打印出来了,但是因为我想让代码更容易阅读所以删除了它们。
  • cutHair() 和 getHaircut() 方法有什么作用?有什么东西会抛出 InterruptedException 吗?
  • 你能贴出完整的代码吗?

标签: java multithreading semaphore


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    1) freeChairs 应该是 AtomicInteger。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2014-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 2020-02-27
      相关资源
      最近更新 更多