12

/Threadのような のメソッドや、別のスレッドからの他のいくつかのメソッドを使用しても安全ですか? APIは何も言いませんが、ソースコードから判断するとsetNamegetName

private char name[];

public final void setName(String name) {
    checkAccess();
    this.name = name.toCharArray();
}

public final String getName() {
    return String.valueOf(name);
}

メモリの一貫性エラーが発生する可能性があるようです。

4

4 に答える 4

4

Thread.getName()は、いつでも誰でも照会できるプロパティです。たとえば、監視ユーティリティは常にすべてのスレッドの名前を照会します。したがって、メソッドはスレッドセーフである必要があります。そうでない場合、誰がいつ安全にアクセスできるかについての明確なプロトコルがありません。

Thread名前を保存するためにaを使用する理由は常に不可解char[]ですが、より重要な質問がありますが、getName()明らかに正しく同期されていません。あるスレッドがそうする場合setName("abcd")、別のスレッドが監視する可能性がありますgetName()->"ab\0\0"

質問をconcurrency-interestlistに投稿します。http://cs.oswego.edu/pipermail/concurrency-interest/2013-March/010935.htmlを参照してください

于 2013-03-14T21:10:50.447 に答える
3

「APIは何も言わない」

APIが何も言わない場合、メソッド/classがスレッドセーフであるとは決して考えられません。ソースコードからわかるように、アクセスはname相互に排他的ではありません。
しかし、私にとっては、それnameは古い値か新しい値のどちらかであり、その間に何もないように思われるので、get/setName().

于 2013-03-14T20:55:21.800 に答える
1

手始めに、へのsetNameアクセスnameが何らかの形で同期されていないときに 1 つのスレッドが呼び出された場合、他のスレッドがその新しい値を参照できるという保証はありません。

次に、 をString.valueOf(char[])繰り返しnameます。つまり、この反復中に の文字の 1 つでも設定nameれた場合、反復スレッドは一貫性のないデータ (元の char 配列の最初の文字と他の文字配列の最後の文字) を参照する可能性があります。

この特定のケースでは、文字の 1 つではなく、char 配列の先頭へのポインターです。配列に対する反復が、現在の反復インデックスをそのポインターの参照アドレスに追加することによってアクセスする次のセルを計算すると仮定すると、実際にはデータの一貫性も失われます。

**編集**

2 番目の安全でないシナリオについては、この質問と回答を読んだ後、配列のコピーが実際にどのように実装されているかがあまり明確ではないように思われます。これはプラットフォームに依存します。String,valueOf(char[])これは、スレッドセーフとして文書化されていない理由を説明しています。とにかく、2 番目のシナリオは非スレッドセーフとして適用されます。

于 2013-03-14T21:48:01.247 に答える
0

スレッドオブジェクトが他のスレッド間で共有されている場合(これは珍しいかもしれませんが、それでも可能です-そのようにソリューションをプログラムした場合)、スレッドセーフではありません。他のクラスやオブジェクトと同様に、競合状態の影響を受けやすくなっています。

例:

Thread t1 = new SomeThread(); t1.start();
(new MyThread(t1, new Runnable() { public void run() {t1.setName("HELLO");} })).start();
(new MyThread(t1, new Runnable() { public void run() {t1.setName("GOODBYE");} })).start();

同じスレッドオブジェクトt1にアクセスする2つのスレッド。危険な。

于 2013-03-14T22:01:25.343 に答える