1

あるものを扱うvolatileなら毎回使うべきではないか。synchronizedmutable state

  1. synchronized私を(状態/スレッド)安全にします
  2. volatileは、 に関するスレッドを更新しshared mutable stateます。

次にvolatile、スレッドの更新が気になる場合は、どこにでも配置する必要がありますか?

編集: 2 つの使用例があります。

1.

1000 スレッドがこのオブジェクトを読み書きします(状態について更新されることを望んでいますa):

 class A {
   private int a;
   public synchronized int getA() {...}
   public void setA(int a) {...}
 }

2.

ThreadA のスレッド数は 1000 です。彼らは状態について更新されることを望んでいますa

class ThreadA extends Thread {
 private int a;
 public void run() { synchronized(a) { ... } }
}
4

2 に答える 2

0

多くのパフォーマンスに関する質問と同様に、真の問題は単純さと明快さです。両方を使用すると混乱する可能性があるため、synchronized または volatile を使用することをお勧めします。両方を使用することは冗長であるため、わずかに非効率的ですが、問題になるほどで​​はありません。コードをできるだけ理解しやすくすることについてもっと心配し、必要以上のことはしません。

最初のケースでは、volatile のみが意味をなします (または、synchronized を一貫して使用する)

class A {
   private volatile int a;
   public int getA() {...}
   public void setA(int a) {...}
 }

2 番目のケースでは、ローカル オブジェクトで同期しても意味がありません。削除できます。私も Thread を拡張しません。これは悪い習慣です。

1000 のスレッドがあるかもしれませんが、8 ~ 16 個の CPU しかない可能性があります。これほど多くの CPU バウンド スレッドを使用することはお勧めできません。スレッドの数を減らすと、オーバーヘッドが減り、パフォーマンスが向上する可能性があります。

それらが可能な限り独立するように設計する必要があります。それができない場合、キャッシュの一貫性がオーバーヘッドにならないため、単一のスレッドの方が高速になる可能性があります。


IMHO列挙型の使用は、Guava MemorizeSupplierを使用するよりも簡単ですが、どちらが高速ですか

public class GuavaMain {
    interface AAA {
        int hashCode();
    }

    enum Singleton implements AAA {
        INSTANCE
    }

    public static void main(String... ignored) {
        Supplier<AAA> memoize = Suppliers.memoize(new Supplier<AAA>() {
            @Override
            public AAA get() {
                return new AAA() {
                };
            }
        });

        for (int j = 0; j < 10; j++) {
            int runs = 5000;
            long time1 = System.nanoTime();
            for (int i = 0; i < runs; i++) {
                // call a method on out lazy instance
                Singleton.INSTANCE.hashCode();
            }
            long time2 = System.nanoTime();
            for (int i = 0; i < runs; i++) {
                // call a method on out lazy instance
                memoize.get().hashCode();
            }
            long time3 = System.nanoTime();
            System.out.printf("enum took %,d ns and memorize took %,d ns avg%n",
                    (time2 - time1) / runs, (time3 - time2) / runs);
        }
    }
}

版画

enum took 179 ns and memorize took 301 ns avg
enum took 74 ns and memorize took 97 ns avg
enum took 62 ns and memorize took 175 ns avg
enum took 58 ns and memorize took 146 ns avg
enum took 58 ns and memorize took 147 ns avg
enum took 56 ns and memorize took 111 ns avg
enum took 36 ns and memorize took 86 ns avg
enum took 36 ns and memorize took 84 ns avg
enum took 36 ns and memorize took 82 ns avg
enum took 36 ns and memorize took 82 ns avg
于 2013-05-23T16:29:16.337 に答える
-1

volatileどこでも使用すると、本質的にコード内に多くの同期ポイントが導入され、効率が低下します。

並行性のためにコーディングする場合、最良の選択は、共有可変性を小さなセクションに分離するか、共有状態を可能な限り排除することです。

于 2013-05-23T16:25:27.760 に答える