lichten さんも指摘するとおり、「スレッドセーフ」が表す意味はかなり曖昧で、対象とする文脈によってその定義が異なります。
.NET Frameworkの文脈ならば、大意としては「あるクラスについて、そのメソッドを異なるスレッドから同時に呼び出しても、仕様通りに動作すると保障される」という感じでしょう。これは、あるクラスのインスタンスに対して、同一メソッドを異なるスレッドから同時に呼び出す/異なるスレッドを異なるスレッドから同時に呼び出す、の両方を含みます。
スレッドセーフとは複数のスレッドから同時に利用されても正常に動作するよう、
ロックの取得を用い、期間内を単一スレッドのみ通過できるものと認識しております。
スレッドセーフは対外的な「仕様」であり、ロックはその「内部実装」と考えたほうがよいです。スレッドセーフを実現するために、内部実装としてロック機構を用いることがよくあります。ただし、ロック機構を用いないスレッドセーフの実現方式もあります。
上記記事でいう各メソッドのスレッドセーフの保障というのはコード内のロックの有無を認識し、
ロックが解除されるまで進めないというものでしょうか?
ここで言うスレッドセーフとは、アプリケーションコードからは呼出スレッドを気にせずに各メソッドを呼び出してよいという意味です。なお、各メソッドが「(アプリケーション)コード内のロックの有無を認識」することはありません(これは実現不可能です)。
逆にスレッドセーフではないメソッドを用いた場合はロックを認識せず動作するということでしょうか?
スレッドセーフでないメソッドを複数スレッドから同時に呼び出すと、何が起こるかは保障されません。間違った結果を返すかもしれませんし、何らかの例外をスローしてくるかもしれませんし、偶然に正しく動くかもしれません。(.NET Framework提供クラスだと、丁寧に例外スローするものがいくつかあるようです)
またスレッドセーフではないメソッドも教えてください。
基本的にスレッドセーフが明記されていない、内部状態をもつクラスのメソッドは、スレッドセーフではありません。言い換えると、内部実装で特別な考慮をしない限り、大半のメソッドはスレッドセーフではありません。例外として、状態を持たないメソッド=出力結果が入力引数にしか依存しないメソッドは、異なるメソッド呼び出し同士が互いに干渉しようがないため、スレッドセーフなメソッドと考えられます。
たとえば、次のメソッドgetUniqueId
はスレッドセーフではありません。一意で重複しないID値を返すことを期待されますが、複数スレッドから同時に呼び出すと、仕様に反した”同じID値”を返す可能性があります。
class Foo {
private int counter = 0;
public int getUniqueId() {
return counter++;
}
}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/02/16 06:39