Java信号量:未正确阻止和释放

Java信号量:未正确阻止和释放,java,concurrency,semaphore,Java,Concurrency,Semaphore,对于我当前的程序,我正在尝试制作一个模拟交叉口程序,将进入交叉口的4条道路中的每一条作为队列,队列中的每一条线程都是一辆“汽车”。每一个模拟时钟滴答作响,一辆汽车就被允许通过,同时修改不同的计数变量 我目前的问题是,我控制时钟滴答作响的信号灯越来越多,在十字路口行驶的车辆似乎无法正常工作。代码如下 public class Intersection implements Runnable{ static ArrayList<Queue<Thread>> streets

对于我当前的程序,我正在尝试制作一个模拟交叉口程序,将进入交叉口的4条道路中的每一条作为队列,队列中的每一条线程都是一辆“汽车”。每一个模拟时钟滴答作响,一辆汽车就被允许通过,同时修改不同的计数变量

我目前的问题是,我控制时钟滴答作响的信号灯越来越多,在十字路口行驶的车辆似乎无法正常工作。代码如下

public class Intersection implements Runnable{

static ArrayList<Queue<Thread>> streets = new ArrayList<Queue<Thread>>();
static ArrayList<Thread> allThreads = new ArrayList<Thread>();
static int clk = 1;
static int numCars = 0;
static boolean empty = true;
static long state = 1;
static int carsRan = 0; 
static int carsMade = 0;
static int carsToRun = 0;

static Random randomGen = new Random();

static Semaphore carCanGo;
static Semaphore clkUp;

public static void main(String[] args) {

    carCanGo = new Semaphore(1);
    clkUp = new Semaphore(0);

    for(int i = 0; i < 4; i++){
        Queue<Thread> newStreet = new LinkedList<Thread>();
        streets.add(newStreet);
    }

    numCars = 50;

    if(numCars > 100){
        numCars = 100;
    }

    while(carsRan  < numCars && clk < 30){
        if(carsMade < numCars){
            newCarsArrive();
            if(carsToRun == 0){
                clkUp.release();
            }
        }

        System.out.println("clockups");

        for(int i = 0; i < allThreads.size(); i++){
            System.out.println(allThreads.get(i).isAlive());
        }

        try {
            clkUp.acquire();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        clk++;
        carCanGo.release();
        System.out.println("clk: " + clk);

        //check for dead processes
        for(int i = 0; i < allThreads.size(); i++){
            if(!(allThreads.get(i).isAlive())){
                try {
                    Thread t = allThreads.get(i);
                    System.out.println("--Thread " + t.getId() + " Done--");
                    allThreads.remove(i);
                    t.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else{
                System.out.println("~~Thread " + allThreads.get(i).getId() + " Not Done~~");
            }
        }
    }
}

public void run() {
    System.out.println("here");

    Thread t = Thread.currentThread();
    if (empty) { 
        System.out.println("empty means go");
        empty = false; 
        try {
            carCanGo.acquire();
            drive(randomGen.nextInt(100), t);
            clkUp.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } 
    }else { 
        Random randomGen = new Random();
        int randomNum = randomGen.nextInt(3);
        int streetNum = randomNum;
        streets.get(streetNum).add(t);
        System.out.println(t.getId() + " | " + streetNum + " | " + randomNum);

        // wait for someone to signal that it is street[i]’s turn to go 
        boolean spin = true;
        while(spin){
            if(t==streets.get(streetNum).peek()){
                spin = false;
            }
        }

        try {
            carCanGo.acquire();
            drive(streetNum, t);
            clkUp.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    } 
}
公共类交集实现可运行{
静态ArrayList街道=新建ArrayList();
静态ArrayList allThreads=新ArrayList();
静态int clk=1;
静态int numCars=0;
静态布尔空=真;
静态长态=1;
静态int carsRan=0;
静态int carsMade=0;
静态int-carsToRun=0;
静态随机生成=新随机();
静态信号量carCanGo;
静态信号量clkUp;
公共静态void main(字符串[]args){
carCanGo=新信号量(1);
clkUp=新信号量(0);
对于(int i=0;i<4;i++){
Queue newStreet=new LinkedList();
街道。添加(newStreet);
}
numCars=50;
如果(numCars>100){
numCars=100;
}
而(carsRan”);
所有螺纹。移除(i);
t、 join();
}捕捉(中断异常e){
e、 printStackTrace();
}
}否则{
System.out.println(“~~线程”+所有线程.get(i).getId()+”未完成~~”;
}
}
}
}
公开募捐{
System.out.println(“此处”);
Thread t=Thread.currentThread();
如果(空){
System.out.println(“空表示开始”);
空=假;
试一试{
carCanGo.acquire();
驱动装置(随机发电机nextInt(100),t);
clkUp.release();
}捕捉(中断异常e){
e、 printStackTrace();
} 
}否则{
Random randomGen=新的Random();
int randomNum=randomGen.nextInt(3);
int streetNum=randomNum;
streets.get(streetNum).add(t);
System.out.println(t.getId()+“|”+streetNum+“|”+randomNum);
//等待有人发出信号说该走了
布尔自旋=真;
while(旋转){
if(t==streets.get(streetNum.peek()){
自旋=假;
}
}
试一试{
carCanGo.acquire();
路(t街);;
clkUp.release();
}捕捉(中断异常e){
e、 printStackTrace();
}
} 
}
代码已被删除,因为已知它可以工作(drive()和newCarsArrive(),可以根据请求重新添加)

大体上,我们在clkUp上获得()然后在carCanGo上释放()。 在Run()中,我们在carCanGo上使用acquire(),然后在clkUp上使用release()。
当一个信号量被初始化为1,另一个信号量被初始化为0时,为什么这不起作用?

没有任何东西是易变的,也没有任何东西是同步的;你到底希望在这里发生什么?自动跨越内存障碍?这是一个巨大的竞争危险。我还注意到那里有一个繁忙的等待和不同步的修改n的非线程安全集合。此代码不能也不会工作;扔掉它。阅读Java并发性教程。重新开始。@Boristeider busy wait是我不确定如何处理的事情,因为我不知道它的标题,所以不确定如何修复它。至于其他所有内容,是否有您建议获得be的指南如何做到这一点?我会从开始。繁忙等待永远不会发生-有一千多种方法可以避免繁忙等待。从最简单的
等待
/
通知
到您已经在使用的更高级的方法,如
信号灯
。实际上,并发和多线程是无法实现的如果您对某些内容理解不够透彻,请参阅oracle java教程中的并发课程: