0

可変クラスの次の構成が表示されます。

public class Doubtful
{

    public static Doubtful getInstance()
    {
        DoubtfulContext doubtfulcontext;//LOCAL HEAP VARIABLE
        //...
        doubtfulcontext = new DoubtfulContext(s1, new PrincipalName(s),
            DefaultConfig.getInstance());
        //...
        doubtfulcontext.setDoubtfulStore(new DoubtfulStore(new File(s2)));
        doubtfulcontext.setKeyTab(...);
        doubtfulcontext.setSupportedEncryptionTypes(ai);
        //...
        return new Doubtful(doubtfulcontext);
    }

    // ...
}

Doubtful は不変かもしれませんが、 DoubtContext は間違いなく変更可能です。
これはスレッドセーフですか?
ここでのローカル ヒープ変数の関連性は何ですか?

4

3 に答える 3

1

ローカル変数は、実行中のスレッドに限定されます。これらは実行中のスレッドのスタックに存在し、他のスレッドからはアクセスできません。これにより、getInstanceメソッドの実行がスレッドセーフになります。

あなたが言ったようDoubtfulに、それは不変であり、スレッドセーフになります。複数のスレッドは、同じDoubtfulインスタンスで作業している他のスレッドに影響を与えることなく、同じインスタンスで作業できDoubtfulます。スレッドはインスタンス変数を変更できず (Doubtful不変)、メソッドのローカル変数は実行中のスレッドに限定されるためです。

現在は変更可能であり、メソッドでローカルに作成されDoubtfulContextたインスタンスへの参照を公開しています:DoubtfulContextgetInstance

doubtfulcontext = new DoubtfulContext(s1, new PrincipalName(s),
        DefaultConfig.getInstance());
...
return new Doubtful(doubtfulcontext);//Publishes the reference to DoubtfulContext

これはスタックの制限に違反します。DoubtfulContextまた、複数のスレッドが同じインスタンスの共有された変更可能なデータにアクセスできる可能性があります。がスレッドセーフでないオブジェクトである場合DoubtfulContext、プログラムが壊れます。

のインスタンスを取得するためにT1呼び出すスレッドを考えてみましょう。その後、他のスレッドと参照 ( に付随する) を共有する可能性があります。getInstanceDoubtfulDoubtfulContextDoubtful

1. Doubtful doubtful = Doubtful.getInstance();
2. DoubtfulContext doubtfulContext = doubtful.getDoubtfulContext();
3. new Thread(new SomeRunnable(doubtfulContext)).start();
4. doubtfulContext.chnageSomeState();

3 行目で、新しい実行スレッドを作成しますDoubtfulContext。これで、2 つのスレッドが同じDoubtfulContext. がDoubtfulContextスレッド セーフでない (インスタンス変数へのアクセスが同期されていない) 場合、プログラムのスレッド セーフが損なわれます。

于 2013-10-23T10:50:42.543 に答える
0

それが正しい選択であるかどうか、このコードが何を言っているのかは明確ではありません。スレッド セーフの問題は、何が変更可能か、またそのオブジェクトが複数のスレッドから参照されるかどうかの問題です。ステートフルであるが、1 つのスレッドによってのみ表示される新しいオブジェクトを作成することは、スレッドセーフです。すべての不変メンバーで不変オブジェクトを作成することは、新しいオブジェクトまたは同じオブジェクトを繰り返し返すかどうかにかかわらず、スレッドセーフです。

変更可能な状態がある場合、オブジェクトが複数のスレッドから見えるかどうかを知る必要があります。はいの場合、変更可能なものがスレッドセーフであることを確認するための対策を講じる必要があります。

いくつかのオプション:

  • すべてを不変にします。それを静的ブロックで初期化し、静的変数に保存します(私は静的変数があまり好きではありません.Guiceのような依存性注入フレームワークを使用して注入すると、よりクリーンで柔軟になります.シングルトンかどうかは起動時に作成されます)。

  • doubtfulContextが共有されておらず、ステートフルな唯一のものである場合、それはステートフルですが、将来の呼び出し元がその新しいインスタンスを取得する場合、メソッドは問題ありません。後でスレッド間で渡される場合は、doubtfulContextそのスレッドセーフを個別に作成する必要がある場合があります

  • たとえば、同じファイルを 1 回だけ読み取り、そのファイルを表すオブジェクトを共有して最適化したい場合は、ある種のスレッドセーフなキャッシュが必要になります。

于 2013-10-23T08:12:43.603 に答える