【问题标题】:Java criticial section seems not workJava 临界区似乎不起作用
【发布时间】:2013-03-16 05:34:58
【问题描述】:

代码如下:

final CountDownLatch lineDirectionLatch = new CountDownLatch(count);
final Object lock = new Object();
for(StationLines station : stationList) {
    final String gpsNumber = station.getGpsNumber();
    for(String lineNumber : station.getLines()) {
        final TranslateToStationTask task = new TranslateToStationTask(lineNumber, gpsNumber);
        task.setCallback(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    Utils.debug(TAG, "Thead " + Thread.currentThread().getId() + " enter critical section.");
                    int errorCode = task.getTaskResult().getErrorCode();
                    if (errorCode == 0) {
                        Station station = task.getTaskResult().getContent();
                        if (station != null) {
                        for(int idx = 0; idx < stationList.size(); idx++) {
                            String gpsNumber = stationList.get(idx).getGpsNumber();
                            if (gpsNumber.equals(station.getGpsNumber())) {
                                    stationList.get(idx).setDirection(station.getLineNumber(), station.getDirection());
                            }
                        }
                        }
                    } 
                    Utils.debug(TAG, "Thead " + Thread.currentThread().getId() + " leave critical section.");
                    lineDirectionLatch.countDown();
                }
            }});
        task.startTask();
    }
}
lineDirectionLatch.await();

这是日志:

03-26 19:57:07.648: I/TrafficManager(20013): Thead 1501 enter critical section.
03-26 19:57:07.687: I/TrafficManager(20013): Thead 1501 leave critical section.
03-26 19:57:07.714: I/TrafficManager(20013): Thead 1502 enter critical section.
03-26 19:57:07.722: I/TrafficManager(20013): Thead 1502 leave critical section.
03-26 19:57:07.726: I/TrafficManager(20013): Thead 1503 enter critical section.
03-26 19:57:07.726: I/TrafficManager(20013): Thead 1503 leave critical section.
03-26 19:57:07.769: I/TrafficManager(20013): Thead 1509 enter critical section.
03-26 19:57:07.773: I/TrafficManager(20013): Thead 1505 enter critical section.
03-26 19:57:07.773: I/TrafficManager(20013): Thead 1505 leave critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1506 enter critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1506 leave critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1507 enter critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1507 leave critical section.
03-26 19:57:07.804: I/TrafficManager(20013): Thead 1510 enter critical section.
03-26 19:57:07.843: I/TrafficManager(20013): Thead 1511 enter critical section.
03-26 19:57:07.843: I/TrafficManager(20013): Thead 1513 enter critical section.

你可以看到线程 1505 在之前进入的线程(1509)之前进入了临界区,并且线程 1509 永远不会离开临界区?很奇怪。

每个 TranslateToStationTask 在它自己的线程中运行,当任务完成时,临界区将被调用。

我不知道为什么临界区允许多个任务进入,为什么有些任务似乎永远不会离开临界区?

【问题讨论】:

    标签: java android concurrency


    【解决方案1】:

    从您的代码看来,您正在函数本身中创建lock 对象。 所以每次调用该函数时,都会为不同的线程创建一个新的锁。

    因此它们都会进入您的关键部分。

    要获得所需的行为,请将其移出此函数。

    【讨论】:

    • 是的,但是日志来自对函数的一次调用。
    • @user1184113 定义你的锁 static 看看会发生什么。
    • 不允许使用静态修饰符。
    • 我曾尝试将锁对象定义为实例变量,但结果仍然不正确。
    【解决方案2】:

    线程 1509 没有将关键部分留在日志中的任何位置。也许它等待lock,什么会允许其他线程进入临界区? (不太可能,因为lock 似乎没有从代码片段中的方法传递到任何地方)。

    【讨论】:

    • 不,TranslateToStationTask 不等待任何锁。
    【解决方案3】:

    请在同步块内添加try-catch子句,查看函数是否异常退出,从而解锁对象,恕不另行通知。

    类似的东西:

    synchronized(lock) {
      try {
        // my code
      }
      catch (Exception e) { // generic catch to look if any exception is triggered
        System.out.printf("Caused exception: %s",e.getMessage());
      }
    }
    

    另一个可能的问题是您使用 new Runnable() 创建了一个匿名类,因此锁可能并不总是同一个变量。尝试创建一个实现 Runnable 的类以及 lock 变量并调用该构造函数。

    【讨论】:

    • 是的,有异常,不通知就释放了锁,非常感谢。
    猜你喜欢
    • 2018-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 2016-11-29
    • 2016-02-01
    • 2020-09-23
    • 2010-12-05
    相关资源
    最近更新 更多