2

以下のクラスでは、singleThreadScheduledExecutor を使用しています。私の質問は、dummyInt と dummyBoolean へのアクセスを同期する必要がありますか?

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Playground {

    /**
     * @param args
     */
    public static void main(String[] args) {
        startThread();

    }

    private static void startThread() {
        ScheduledExecutorService timer = Executors
                .newSingleThreadScheduledExecutor();
        Runnable r = new Runnable() {
            int dummyInt = 0;
            boolean dummyBoolean = false;

            @Override
            public void run() {
                dummyInt = dummyInt + 1;

                if (dummyBoolean) {
                    dummyBoolean= false;
                } else {
                    dummyBoolean= true;
                }

            }

        };

        timer.scheduleAtFixedRate(r, 0, 100, TimeUnit.MILLISECONDS);

    }

}
4

6 に答える 6

3

いいえ、あなたはしません。値にアクセスするスレッドは 1 つだけなので、同期は必要ありません。

于 2010-03-07T17:06:59.463 に答える
2

そのメカニズムで開始するすべてのスレッドには、定義してインスタンス化する「Runnable」サブクラスの独自のインスタンスがあります。したがって、競合が発生する可能性はありません。

于 2010-03-07T17:07:24.780 に答える
1

あなたはする必要がありますか?いいえ。現在の実装では単一のスレッドのみが変数にアクセスするため、スレッドセーフです。

パフォーマンスに悪影響を及ぼしますか?ええ、そうですが、おそらくあなたが期待するほどではありません。最新のJITコンパイラは、現在の使用法では同期が不要であることを認識し、コンパイルされたコードから実質的にすべてのオーバーヘッドを排除しますが、シングルスレッドアクセスの前提がまだあるかどうかを確認するオーバーヘッドが少し残っています。有効。そしてもちろん、これをJITするオーバーヘッドがあります。

同期しないのが痛いことはありますか?まあ、おそらく、実装が変更され、シングルスレッドアクセスの仮定がもはや保持されなくなった場合、変更を行った開発者は、変更の結果を見落としていました。

しかし、実際には、この文脈では、それは起こりそうですか?多分そうではありません-すべてのコードは非常に小さな領域に含まれています...

私はおそらく、仮定を文書化するある種のコメントを残すでしょう。プロジェクトの他の場所でJCIPアノテーションを使用している場合は、クラスに@NotThreadSafeアノテーションを付けることもできます。これらの注釈の使用に関する説明は、 BrianGoetzによるJavaConcurrency In Practiceの本にあり、注釈のソースコードとjarファイルは本のWebサイトからダウンロードできます。

于 2010-03-10T17:16:58.440 に答える
0

あなたはそれを作る必要はありませんsynchronized

于 2010-03-07T18:00:05.187 に答える
-1

いいえ、しかしおそらく害はないでしょう。それを約束するnewSingleThreadScheduledExecutorを使用しているので

タスクは順次実行されることが保証されており、一度に複数のタスクがアクティブになることはありません。

しかし、エグゼキュータを変更した場合は、他の人がそれを呼び出すことができるように Runnable を取り出したり、値を外部からチェックしたりできるようにすると、それを同期したいと思うでしょう。

于 2010-03-07T17:09:55.053 に答える
-2
dummyInt = dummyInt + 1;

このステートメントは、実際には 3 つの別個の操作です。

  1. dummyInt の値を読み取ります
  2. 1を追加
  3. 値を dummyInt に書き戻します

はい、これを同期する必要があります。1 つのスレッドが値を読み取ってから、別のスレッドが 3 つの操作をすべて実行し、最初のスレッドが終了すると、値が 1 だけ増加する可能性があります (これが意味をなすことを願っています:P)。dummyBoolean似ている。if ステートメントでそれを読み取り、新しい値を書き込みます。

編集

質問を正しく読んでおらず申し訳ありません。javadoc によると、これは同期を必要としないはずです。

于 2010-03-07T17:03:48.397 に答える