java - 多线程简单死锁错误逃避检测

标签 java multithreading deadlock

我正在类里面学习多线程,所以请不要实现解决方案;不过,改进建议值得赞赏。

10,000 英尺概述:main 接受 3 个参数(线程、资源和运行时长度)。每个线程等待随机时间,然后决定随机访问共享资源/关键部分,完成后放弃资源。重复提供的运行时长度,然后退出所有线程。

针对卡丁车赛道上用户轮流骑行、骑行间隙闲逛的问题。

我已经造成了僵局,但我不知道这是怎么回事。

Sleeper只是分配线程等待一段时间。

骑手级别:

public void run() {
        while (!coord.exit) {
            System.out.format("Rider %d is gone walkabout%n", ID);
            Sleeper.walkAround(ID);
            System.out.format("Rider %d is in line%n", ID);
            try {
            carID = coord.getInLine();
            System.out.format("Rider %d is riding car %d%n", ID, carID);
            Sleeper.rideTime(ID);
            coord.returnCar(carID);
            } catch (InterruptedException ie) {System.out.println("Thread " + ID + " was interrupted.");}
        }
    }

Coordinator 类是关键所在:

public class Coordinator {

    Rider[] riderArr;
    Semaphore mutex = new Semaphore(1);
    Semaphore cars;
    LinkedList<Integer> carLine;
    volatile static boolean exit = false;

    public synchronized int getInLine() throws InterruptedException {
        cars.acquire();
        mutex.acquire();
        int carid = carLine.removeFirst();
        mutex.release();
        return carid;
    }

    public synchronized void returnCar(int carID) throws InterruptedException {
        mutex.acquire();
        carLine.add(carID);
        mutex.release();
        cars.release();
    }

    public Coordinator(int cars, int riders) {
        riderArr = new Rider[riders];
        for (int i = 0; i < riders; i++) {
            riderArr[i] = new Rider(this, i + 1);
        }
        carLine = new LinkedList<Integer>();
        for (int i = 0; i < cars; i++) {
            carLine.add(i + 1);
        }
        this.cars = new Semaphore(cars);
    }

    public static void main(String[] args) throws NumberFormatException, InterruptedException {
        Coordinator coord = new Coordinator(Integer.parseInt(args[0]),
                Integer.parseInt(args[1]));
        for (int i = 0; i < Integer.parseInt(args[1]); i++) {
            coord.riderArr[i].start();
        }
        Thread.sleep(1000 * Integer.parseInt(args[2]));
        exit = true;
        for (int i = 0; i < Integer.parseInt(args[1]); i++) {
            coord.riderArr[i].join();
        }
        System.exit(0);
    }
}

以下是死锁 session 的控制台输出:

Rider 2 is gone walkabout
Rider 2 is walking around for  4 seconds
Rider 1 is gone walkabout
Rider 1 is walking around for  1 seconds
Rider 1 is in line
Rider 1 is riding car 1
Rider 1 is riding for 3 seconds
Rider 2 is in line

最佳答案

这是一个死锁场景:

  • N 个线程获取 cars 中的所有 N 个 Semaphore token
  • 线程 X 进入 getInLine 并等待 cars#acquire

因为 getInLine同步并且 X 拥有锁,所以 N 个线程中的任何一个都无法返回 token 。这是因为 returnCar 方法也是同步


实现目标的更好方法是将 carLine#removeFirstcarLine#add 放在它们自己的 synchronized 方法中,并且从其他两个方法中删除 synchronized:

public synchronized int removeCar(){
    return carLine.removeFirst();
}

public synchronized void addCar(int car){
    carLine.add(car);
}

这也消除了您对互斥对象的需要。您可以使用 Coordinator 对象本身作为互斥锁。这也意味着等待信号量上的获取不会阻止您返回其 token

关于java - 多线程简单死锁错误逃避检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36561725/

相关文章:

java - CloverETL 图具体

java - 实现生产者消费者模式

android - 在 Eclipse 上调试时无法使用 F5 步入功能

xml - 在后台线程上将 XML 解析为 CoreData 以不锁定 UI

c# - 为什么 ASP.NET Core Web API 中没有出现这种死锁?

multithreading - 锁定层次结构和读写器互斥体

java - 无法获得正确的类路径

java - struts 1 验证不起作用

c - 为什么在克隆系统调用后重新分配死锁?

java - Eclipse 无法解析类型,但类位于构建路径上