变量互斥不起作用

时间:2019-07-18 22:14:12

标签: java multithreading

我正在尝试模拟参观者进入剧院并坐上一个可供使用的座位(共享可用座位的数量),一旦所有座位都被占用,其余的就进入睡眠状态。 我在访问者类内部的getsit方法中的availablesits变量上遇到了麻烦。 请帮助我

我尝试同步线程以及使变量可变。但是由于某些原因,所有线程同时到达该getit部分?我不明白为什么! //主要

import java.util.ArrayList;
public class Main {
    public static void main(String[] args) {
        int numVisitors = 23;
        int theaterCapacity =5;
        int party_ticket=3;
        Clock clock = new Clock();
        Theater theater=new Theater(theaterCapacity,clock);
        ArrayList<Visitor> visitorlist = new ArrayList<Visitor>();
        for(int i=1;i<=numVisitors;i++) {
            visitorlist.add(new Visitor(i,clock,theater));
        }
        clock.start();
        for(Visitor visitor:visitorlist)
            visitor.start();

    }
}

//访客班

  public class Visitor extends Thread{


  private static Clock clock;
    private static Theater theater;
    public int id;
    public boolean sawPresentation=false;
    public volatile int priority= 10;
    public static long time = System.currentTimeMillis();
    public void msg(String m) {
        System.out.println("["+(System.currentTimeMillis()-time)+"] "+getName()+": "+m);
    }
    Visitor(int id, Clock clock, Theater theater){
        this.id=id;
        this.clock=clock;
        this.theater=theater;
    }
    public void run(){
        heArrives();
        while(!sawPresentation) {
            while(!clock.presentationIsOpen()) {
                //busy wait
            }
            getASit();
        }
    }
    public void heArrives() {
      msg("the visitor arrived");
    }
    public synchronized  void getASit(){
        if(theater.availableSits>0){
            msg("the visitor got a sit");
            theater.availableSits--;
            watchPresentation();
        }
    }
    public void watchPresentation(){
        msg("the visitor is watching the presentation");
    }
}

//时钟类

import java.util.Timer;
import java.util.TimerTask;
public class Clock extends Thread {
    public static long time = System.currentTimeMillis();
    public static int secondsPassed=6;
    Timer timer= new Timer();

    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            secondsPassed++;
            //System.out.println("seconds passed: "+secondsPassed);
        }
    };
    public void run(){
        timer.scheduleAtFixedRate(task,0,1000);
    }
    public boolean presentationIsOpen(){
        if(secondsPassed%6==0) return true;
        return false;
    }
}

//剧院课

class Theater extends  Thread{
    public static Clock clock;
    public int capacity;
    public volatile int availableSits=5;
    Theater(int capacity,Clock clock){
        this.capacity=capacity;
        this.clock=clock;
    }
}

1 个答案:

答案 0 :(得分:1)

您的主要问题是getASit方法的同步。您正在针对Visitor对象实例进行同步,因此每个线程都针对不同的对象进行了同步。相反,您必须针对共享的对象进行同步。就您而言,反对剧院。将您的方法更改为如下所示:

 public   void getASit(){
    synchronized(theater){
        if(theater.availableSits>0){
            msg("the visitor got a sit");
            theater.availableSits--;
            watchPresentation();
        }
      }
    }

最好不要使用繁忙的等待,它会消耗过多的CPU,例如,最好使用睡眠:

while(!clock.presentationIsOpen()) {
          try {
              Thread.sleep(1_000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }