在RailStation.java中的Java Lock和条件

时间:2015-11-26 17:34:53

标签: java multithreading locking conditional

这是我从OCPJ SE7中挑选的例子。 一些程序如何卡在WaitForJoe类中,只有我得到的输出如下。虽然有时我得到了完整的输出。

  

IC1122 - 马德里到巴黎锁定列车课程

     

IC1122 - 马德里到巴黎:我已到达车站

     

IC1122 - 马德里向巴黎发送信号

     

在车站等待乔来的IC1122

     

在WaitForJoe类中的Thread-1锁定

import java.util.concurrent.locks.*;

class MyStack {

    private static Lock station = new ReentrantLock();

    private static Condition joeArrival = station.newCondition();
    //private static Condition syncc = station.newCondition();
    public static volatile boolean flag = false ;

    static class Train extends Thread {
        public Train(String name) {
            this.setName(name);
        }
        public void run() {
            System.out.println(getName() +"  Locking in train class");

            station.lock();
            try {
                System.out.println(getName() + ": I've arrived in station ");
                if(getName().startsWith("IC1122")) {
                    System.out.println(getName() +"  sending signal ");
                    while (!flag){}
                    joeArrival.signalAll();
                }
            }
            finally {
                System.out.println(getName() +"  UnLocking in train class");
                station.unlock();
            }
        }
    }

    static class WaitForJoe extends Thread {
        public void run() {
            System.out.println("Waiting in the station for IC1122 in which Joe is coming");
            System.out.println(getName() +"  Locking in WaitForJoe class");

            station.lock();
            System.out.println( "    unlocking " + station.toString());
            try {
                System.out.println(getName() +"  waiting !!!!");
                flag = true ;
                joeArrival.await();
                System.out.println("Pick up Joe and go home");
            } catch(InterruptedException ie) {
                ie.printStackTrace();
            }
            finally {
                System.out.println(getName() +"  UnLocking in WaitForJoe class");
                station.unlock();
            }
        }
    }

    public static void main(String []args) throws InterruptedException {
        new Train("IC1122 - Madrid to Paris").start();

        new WaitForJoe().start();
    }
}

1 个答案:

答案 0 :(得分:0)

这里的问题是,当发送信号时,没有任何东西在等待joeArrival。信令条件仅唤醒当前正在等待它的线程。在你的程序中,WaitForJoe和Train被站锁相互排除。因此,当火车锁定车站时WaitForJoe正在等待它。火车不会解锁,直到它将信号发送到joeArrival,因此WaitForJoe不会在joeArrival上等待,直到信号发送完毕为止。

当WaitForJoe线程首先获得站锁时,您可以获得完整的输出。在这种情况下,ReentrantLock在等待条件时被释放,而Train线程确实最终发出信号。

您是否考虑使用CountDownLatch来模拟此交互?它大大简化了实施......

private static CountDownLatch joeArrival = new CountDownLatch(1);
public static volatile boolean flag = false ;

static class Train extends Thread {
    public Train(String name) {
        this.setName(name);
    }
    public void run() {
        System.out.println(getName() +"  Locking in train class");

        System.out.println(getName() + ": I've arrived in station ");
        if(getName().startsWith("IC1122")) {
            System.out.println(getName() +"  sending signal ");
            while (!flag){}
            joeArrival.countDown();
        }

    }
}

static class WaitForJoe extends Thread {
    public void run() {
        System.out.println("Waiting in the station for IC1122 in which Joe is coming");
        System.out.println(getName() +"  Locking in WaitForJoe class");

        try {
            System.out.println(getName() +"  waiting !!!!");
            flag = true ;
            joeArrival.await();
            System.out.println("Pick up Joe and go home");
        } catch(InterruptedException ie) {
            ie.printStackTrace();
        }

    }
}