0

我正在使用线程编写一个理发店程序。目前我有一个理发师和多个客户同时进来。然而,在第一次运行程序之后,其余的客户都搞砸了。他们都同时坐下。有什么我错过的吗?我的代码是:

public synchronized void enter(Customer cust) {
    custList.add(cust);
       getCut(cust);
     }
      public synchronized void getCut(Customer cust) {    
    try {    
      notify(); 
      wait(); 


      System.out.println("sit down");
      notify();
      if (cashier==0) {
        cashier++;
        wait();
        System.out.println("waiting to pay");
        notify();     
        wait();
        System.out.println("left the room"); 
        chairs++; 
        cust.terminate(); 
      }



    } catch (InterruptedException ie) {}

  }

这是我的理发师部分:

 public synchronized void cut(Barber barb) {

    cashier=0;

    try { 
     if(temp){
       System.out.println(temp);
        temp = false;
        notify();
        wait(); //wait for the customer to be settled in
        System.out.println("go to cus");
        notify(); 
        wait();


        System.out.println("cut cus hair");
        notify(); 

        wait();
        if (cashier==1) {

          System.out.println("got money");
          notify();
          cashier--;

          barbers++;

        }
     }      
    } catch (InterruptedException ie) {}

  }
}
 public synchronized void goCut(Barber barb) {

cashier=0;

try { 
 if(temp){
   System.out.println(temp);
    temp = false;
    notify();
    wait(); 
    System.out.println("walks to cus");
    notify(); 
    wait();


    System.out.println("cut hair");
    notify()

    wait();
    if (cashier==1) {

      System.out.println("got the money");
      notify();
      cashier--;
      barbers++;

    }
 }  
4

3 回答 3

0

看起来您正在notify随机wait使用。

你有

notify();
wait();

getCut方法的开头,它的作用是:

  • 第一个客户端进来,它调用通知,然后等待
  • 第二个客户端进来,它调用通知 - 因此它唤醒第一个客户端,然后等待
  • 第三个客户端进来,它调用通知 - 结果第二个客户端唤醒,依此类推

相反,您应该使用通知和唤醒来阻止特定资源(椅子)。

private final Object pChairLock = new Object();
private int pAvaliableChairs = 3;

...

// take the resource
synchronized(pChairLock)
{
    // wait until a chair is avaliable
    while(pAvaliableChairs == 0)
    { 
        pChairLock.wait();
    }

    // take sit
    pAvaliableChairs--;
}

// now the current thread 'is sitting'
//  - it can do some work using the resource

// after finishing, release the resource
synchronized(pChairLock)
{
    pAvaliableChairs--;

    // notify all waiting thread that resource is available
    pChairLock.notifyAll();
}

在这种情况下,您可以只使用 notify(),但如果不同的线程正在等待释放资源并获取它,那么调用 notify 可能会唤醒错误的线程。不要担心同时唤醒太多线程,因为每个线程都会检查资源是否可用,只有第一个线程能够获取它 - 其余线程将继续等待。

此示例使用三把椅子,但您可以只使用一个(布尔值)或任何其他数字。你可以对收银员做同样的事情。

于 2013-04-16T04:23:29.350 回答
0

从甲骨文网站

注意:始终在测试等待条件的循环内调用等待。不要假设中断是针对您正在等待的特定条件,或者条件仍然为真。

请参考Guarded blocks multithreading

于 2013-04-16T00:05:43.027 回答
0

使用下面的代码作为模板(来自 Magee & Kramer 的教科书)......

  • 生产者消费者 = 理发店
  • 创建大小为 1 的 BarberShop
  • get = giveCut(理发师“得到”一位顾客并给顾客理发)
  • put = getCut(客户要求理发 - 即“提出”客户要求理发)

代码:

public class ProducerConsumer {
  protected Object[] buf;
  protected int count = 0;
  protected int size;

  public ProducerConsumer(int size) {
    this.size = size;
    buf = new Object[size];
  }

  public synchronized void put(Object o) throws InterruptedException {
    while (count == size) wait();
    buf[count] = o;
    ++count;
    notifyAll();
  }

  public synchronized Object get() throws InterruptedException {
    while (count == 0) wait();
    --count;
    Object o = buf[count];
    buf[count] = null;
    notifyAll();
    return (o);
  }
}
于 2013-04-16T22:43:16.760 回答