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