首页 > 解决方案 > Java - Dekkers 算法实现导致临界区中有两个线程

问题描述

我正在尝试为有两条铁路的场景实施 Dekkers 算法,并且有一点它们都使用轨道的同一部分。一次只能允许一列火车进入该部分,并且一列火车可以连续通过任意次数,除非其他火车都在转弯并且准备通过。

下面是我为第一条铁轨实现的代码。

while (allowed) {
        choochoo();
        setWantToUseTrack(0,true);
        while (getWantToUseTrack(1)) {
            if (getTurn() != 0) {
                setWantToUseTrack(0,false);
                while (getTurn() != 0) {
                    //wait loop
                }
                setWantToUseTrack(0, true);
            }
        }
        //critical section starts
        crossPass();
        //critical section ends
        setTurn(1);
        setWantToUseTrack(0,false);
    }
}

下面是我实现第二条铁路的代码。

while (allowed) {
        choochoo();
        setWantToUseTrack(1,true);
        while (getWantToUseTrack(0)) {
            if (getTurn() != 1) {
                setWantToUseTrack(1,false);
                while (getTurn() != 1) {
                    //wait loop
                }
                setWantToUseTrack(1,true);
            }
        }
        //critical section starts
        crossPass();
        //critical section ends
        setTurn(0);
        setWantToUseTrack(1,false);
    }

当这段代码运行时,有时两列火车会同时进入临界区。我看不到逻辑错误。我在我的实施中遗漏了什么吗?

标签: javamultithreadingalgorithmjvmjava-threads

解决方案


可能会发生以下情况(仅一个示例):

  1. 在第二个轨道setWantToUseTrack(1,false);被调用。
  2. 在第一个跟踪谓词被检查:while (getWantToUseTrack(1)),到第二个线程没有停止在while循环中。

    这是绝对可行的,因为第一个轨道可以在choochoo();(1.) 之前停止,而第二个轨道可以在 (2.) 发生之前停止。

  3. 方法getWantToUseTrack返回false0 和 1。

创建一个循环来捕获线程直到关键部分被释放是有点危险的。您可能希望通过使用synchronizedwith crossPassdefinition 使部分线程安全。


推荐阅读