Java关键部分似乎不起作用

时间:2013-03-26 12:12:20

标签: java android concurrency

以下是代码:

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();

Herer是日志:

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

我不知道为什么关键部分允许多个任务进入,以及为什么某些任务似乎永远不会离开关键部分?

3 个答案:

答案 0 :(得分:4)

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

因此他们都将进入你的关键部分。

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

答案 1 :(得分:2)

请在synchronized块中添加一个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());
  }
}

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

答案 2 :(得分:0)

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

相关问题