8

次のクラスがあり、頻繁に読み取られますが、たまにしか書き込まれないとしましょう。マルチスレッドのウェブアプリで使用されるため、スレッドセーフである必要があります。

public class Foo {
    private volatile String foo;
    public String getFoo() {
        return foo;
    }
    public synchronized String setFoo(String in) {
        this.foo = in;
    }
}

Java Concurrency(http://www.ibm.com/developerworks/java/library/j-jtp06197/index.html)は、これが読み取りアクセスを改善しながら書き込みアクセスを保護するための脆弱な方法であると述べています。このパターンのより強力な代替手段は何ですか?または、読み取りが多い環境でfooを変更可能にする必要がある場合は、別の方法がありますか?ありがとうございました。

4

3 に答える 3

15

Volatileは、同期なしでフィールドへの高速スレッドセーフロックフリーアクセスを提供します

private volatile String foo;

public String getFoo() {
    return foo;
}
public void setFoo(String in) {
    this.foo = in;
}

volatileは、3つの問題を解決します。1)メモリの可視性2)doubleフィールドとlongフィールドのアトミック書き込み3)命令の並べ替えを禁止します。ただし、インクリメントなど、1つのアトミックトランザクションとしてフィールドに対して複数の操作が必要な場合は、十分ではありません。このコードは壊れています

private volatile int id;

public void incrementId() {
     id++;
}

2つのスレッドが同時にそれを読み取り、インクリメントして結果を保存すると、最初のインクリメントの結果が2番目のインクリメントの結果で上書きされるためです。これを防ぐには、同期を使用する必要があります

 private int id;

 public synchronized int nextId() {
       return ++id;
 }

またはjava.util.concurrent.atomicパッケージ

 private AtomicInteger id = new AtomicInteger();

 public void incrementId() {
     return id.incrementAndGet();
 }
于 2013-03-05T01:43:59.793 に答える
2

fooを設定するだけの場合は、メソッドを同期する必要はありません。参照を揮発性にするだけで十分です。

于 2013-03-05T01:44:08.373 に答える
2

あなたが言ったリンクで、「まれな更新」の使用法のためのこのコードがあります:

@ThreadSafe
public class CheesyCounter {
    // Employs the cheap read-write lock trick
    // All mutative operations MUST be done with the 'this' lock held
    @GuardedBy("this") private volatile int value;

    public int getValue() { return value; }

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

このincrementメソッドは同期のみを使用しています。これはvalue、説明に記載されているようにの値を設定するだけではなく、this.foo = in;アトミックである場合にのみ実行されるためです。本文中の「このパターンの脆弱性」とは、揮発性の方法と他の同期方法を組み合わせて単純な例以上のことを行うと、物事が非常に速く乱雑になる可能性があることを意味します。インターフェイスConditionLockおよびクラスReentrantLockについては、パッケージjava.util.concurrent.locksを参照してください。私は、同期を使用することは、著者が「より強力な代替手段」によって意味することだと思います。まだわからない場合は、 Object.waitObject.notifyObject.notifyAllも表示されます。

于 2013-03-05T09:53:01.397 に答える