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

もう1つの考えられる問題は、新しいRunnable()を使用して匿名クラスを作成するため、ロックが常に同じ変数であるとは限らないことです。Runnableをlock変数と一緒に実装するクラスを作成し、そのコンストラクターを呼び出してみてください。

于 2013-03-26T12:31:41.793 に答える
0

スレッド1509は、ログのどこにもクリティカルセクションを残していません。おそらくそれは待っていますlock、他のスレッドがクリティカルセクションに入るのを許可するのは何ですか?(可能性は低いlockですが、コードフラグメントのメソッドのどこにも渡されていないようです)。

于 2013-03-26T12:24:07.710 に答える