4

这是代码:

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 在它自己的线程中运行,当任务完成它的工作时,临界区将被调用。

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

4

3 回答 3

4

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

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

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

于 2013-03-26T12:16:25.687 回答
2

请在同步块中添加一个 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 变量并调用该构造函数。

于 2013-03-26T12:31:41.793 回答
0

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

于 2013-03-26T12:24:07.710 回答