16

Javaでintをアトミックかつスレッドセーフに変更するにはどうすればよいですか?

原子的にインクリメント、テスト&セットなど...?

4

3 に答える 3

31

AtomicIntegerを使用します。

于 2009-07-20T08:29:55.927 に答える
1

スレッドセーフは、同期機能を介して実現できます。同期されたメソッドを介して必要な機能を提供するクラスでint(またはそのようなデータ)をラップします。

public class X
{
  protected int x;
  public synchronized void set( int value )
  {
    x = value;
  }
}

java.util.concurrent.atomicパッケージのクラス(AtomicIntegerやAtomicIntegerArrayなど)を使用することもできます。

この答えがうまくいかない理由

synchronizedスレッドレースの影響を解決するために使用できるものがある場合に備えて、この回答の何が問題になっているのかを正確に指摘したかっただけです。

| Thread A      | Thread B         | 
|---------------|------------------|
| read x (x=4)  |                  |
|               | read x (x=4)     |
| Calculate 4+1 |                  |
| EAX ← 5       |                  |
|               | Calculate 4+1    |
|               | EAX ← 5          |
| Start sync    |                  |
| {             | Start sync       |
| { x ← 5       |    wait          |
| {             |    wait          |
| End sync      |    wait          |
|               | {                | 
|               | { x ← 5          |
|               | {                | 
|               | End sync         |

操作の最終結果:

x = 4;
x += 1;
x += 1;

x= 6ではなく5です。

volatileキーワードにも同じ問題があります。キーワードはvolatileスレッド効果からあなたを救いません。volatileキーワードは、

  • 変数が読み取られる前にキャッシュがフラッシュされます
  • 値が書き込まれた後、キャッシュがフラッシュされます

厳密に言えば、volatileメモリ操作が揮発性変数の周りで並べ替えられないようにします。それはあなたがまだ苦しんでいることを意味します:

  • xから読み取る
  • xに書き込む

問題。

于 2009-07-20T08:31:38.000 に答える