0

次のように静的ゲッターとセッターを同期しました:

public synchronized static int getValue() {
    return value;
}

public synchronized static void setValue(int Val) {
    value = Val;
}

値を増やす必要がある場合は、次のようなものを使用します

setValue(getValue() + 1);

「値」を設定し、すぐに「値」を取得しようとするスレッドが存在する可能性があります。このような場合、デッドロックが発生する可能性はありますか? はいの場合、それを回避する方法は?

4

5 に答える 5

5

「値」を設定し、すぐに「値」を取得しようとするスレッドが存在する可能性があります。このような場合、デッドロックが発生する可能性はありますか? はいの場合、それを回避する方法は?

2 つのロックが関与しない限り、デッドロックにはなりません (デッドロックの定義を参照)。ただし、get呼び出されてから setter が呼び出されると、競合状態が発生します。たとえば、2 つのスレッドがgetValue()値メソッドを順番に呼び出してから、戻ってsetValue(...)別のメソッドを呼び出すことができます。2 番目のセッターは、もう一方のインクリメントを上書きします。

  1. getValue()1 に等しいスレッド a 呼び出し
  2. getValue()1 に等しいスレッド b 呼び出し
  3. thread-a は値をインクリメントします
  4. スレッド a はsetValue(...)、増分値 2 で呼び出します
  5. thread-b は値をインクリメントします
  6. setValue(...)増分値 2 でのスレッド b 呼び出し

したがって、答えは 3 になるはずですが、競合状態のために 2 になります。

コードを続けると、get、increment、および set の両方synchronized static void increment()を行うメソッドが必要になります。はアトミック操作ではないため、そうする必要があります。synchronized++

public synchronized static int increment() {
    value++;
}

AtomicInteger以上のことから、インクリメントとメモリ同期に関する競合状態を処理する代わりに を使用することを検討する必要があります。

于 2013-10-22T14:26:58.100 に答える
0

この場合、同期メソッドは必要ありません。value変数を次のようにマークするだけです。volatile

volatile private Object var;

ただし、読み取り変更更新の場合はオブジェクトを同期する必要がありますが、同期メソッドには注意してください。これは、null ではないオブジェクト参照を受け入れるため (プリミティブは許可されていません)、コードは次のようになります。

volatile static private int value;
public int getValue(){return value;}
public void setValue_direct(int id){value=val;}
public synchronized void setValue_increment(){value++;}

このリンクは、揮発性キーワードについて役立ちます

于 2013-10-22T14:52:27.523 に答える