質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

3回答

11018閲覧

スレッドセーフとは?

ranran

総合スコア85

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

5クリップ

投稿2015/02/15 11:47

お世話になります。

ある記事にて「Invoke,BeginInvoke,EndInvoke...等」メソッドはスレッドセーフが保障されているとありました。

スレッドセーフとは複数のスレッドから同時に利用されても正常に動作するよう、
ロックの取得を用い、期間内を単一スレッドのみ通過できるものと認識しております。

上記記事でいう各メソッドのスレッドセーフの保障というのはコード内のロックの有無を認識し、
ロックが解除されるまで進めないというものでしょうか?

逆にスレッドセーフではないメソッドを用いた場合はロックを認識せず動作するということでしょうか?

勉強し始め日が浅いのでスレッドセーフに対する認識そのものが間違っているかもしれません。
どなたか詳しい方ご教授いただけないでしょうか。

またスレッドセーフではないメソッドも教えてください。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

lichten さんも指摘するとおり、「スレッドセーフ」が表す意味はかなり曖昧で、対象とする文脈によってその定義が異なります。

.NET Frameworkの文脈ならば、大意としては「あるクラスについて、そのメソッドを異なるスレッドから同時に呼び出しても、仕様通りに動作すると保障される」という感じでしょう。これは、あるクラスのインスタンスに対して、同一メソッドを異なるスレッドから同時に呼び出す/異なるスレッドを異なるスレッドから同時に呼び出す、の両方を含みます。

スレッドセーフとは複数のスレッドから同時に利用されても正常に動作するよう、
ロックの取得を用い、期間内を単一スレッドのみ通過できるものと認識しております。

スレッドセーフは対外的な「仕様」であり、ロックはその「内部実装」と考えたほうがよいです。スレッドセーフを実現するために、内部実装としてロック機構を用いることがよくあります。ただし、ロック機構を用いないスレッドセーフの実現方式もあります。

上記記事でいう各メソッドのスレッドセーフの保障というのはコード内のロックの有無を認識し、
ロックが解除されるまで進めないというものでしょうか?

ここで言うスレッドセーフとは、アプリケーションコードからは呼出スレッドを気にせずに各メソッドを呼び出してよいという意味です。なお、各メソッドが「(アプリケーション)コード内のロックの有無を認識」することはありません(これは実現不可能です)。

逆にスレッドセーフではないメソッドを用いた場合はロックを認識せず動作するということでしょうか?

スレッドセーフでないメソッドを複数スレッドから同時に呼び出すと、何が起こるかは保障されません。間違った結果を返すかもしれませんし、何らかの例外をスローしてくるかもしれませんし、偶然に正しく動くかもしれません。(.NET Framework提供クラスだと、丁寧に例外スローするものがいくつかあるようです)

またスレッドセーフではないメソッドも教えてください。

基本的にスレッドセーフが明記されていない、内部状態をもつクラスのメソッドは、スレッドセーフではありません。言い換えると、内部実装で特別な考慮をしない限り、大半のメソッドはスレッドセーフではありません。例外として、状態を持たないメソッド=出力結果が入力引数にしか依存しないメソッドは、異なるメソッド呼び出し同士が互いに干渉しようがないため、スレッドセーフなメソッドと考えられます。

たとえば、次のメソッドgetUniqueIdはスレッドセーフではありません。一意で重複しないID値を返すことを期待されますが、複数スレッドから同時に呼び出すと、仕様に反した”同じID値”を返す可能性があります。

class Foo { private int counter = 0; public int getUniqueId() { return counter++; } }

投稿2015/02/16 04:32

編集2015/02/16 04:58
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ranran

2015/02/16 06:39

前知識としlichtenさんのリンク先を見ましたので、すんなり入りました。 .NET Frameworkの文脈としてどういう意味なのか。 スレッドセーフとロックのとらえ方。 大変参考になりました、ありがとうございました。
guest

0

大体においてスレッドセーフという言葉には、複数のスレッドから同時にアクセスされても問題ない変数、という意味が込められていますが、対象のプログラムの目的によって、その定義にはいくらか揺らぎがあります。

質問者さんが挙げられているような、APIのマニュアルにおいて「スレッドセーフ」という言葉が用いられる場合、たいていは「複数のスレッドからアクセスされても例外を出さない、プログラムがクラッシュしない」というような意味です。

しかしプログラムの目的によっては、例外が出ないだけでは不適切です。

例えば対象が、100個のデータを管理する変数だとします。
その100個のデータに対して、1つ目から順に処理するスレッドと、50個目から変更するスレッドが同時に動いたらどうなるでしょうか? 結果は不定です。
この例では、排他処理 (C#なら lock ステートメントなど) と呼ばれる処置が必要になります。

このスレッドセーフという言葉の揺らぎについては、IBM DeveloperWorks の Javaの理論と実践: スレッド・セーフの特性について という良い記事があります。
少し古くて、読みにくい翻訳記事ですが、スレッドセーフという言葉が、普段いい加減に使われていることがわかる内容になっています。

投稿2015/02/16 00:13

lichten

総合スコア133

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ranran

2015/02/16 06:35

リンク先の5段階の分類体系になるほど! と思わされました。 スレッドセーフ自体の認識が間違っていたようです。 勉強になりました、ありがとうございます。
guest

0

古い知識なので見当違いだったらごめんなさい。

スレッドセーフは、マルチスレッドで同じライブラリなどを利用した際に他のスレッドの処理に影響を与えない事だと認識しています。
メモリ上の同じ場所を複数スレッドで使わない、など。
ロックは排他制御のためのものと認識しています。

スレッドセーフではない関数というのは、マルチスレッドで動作すると他のスレッドの処理が自分のスレッドの処理結果に影響をおよぼす恐れがある、という認識です。

スレッドセーフではないメソッドは。。。わかりません。。。

投稿2015/02/15 14:53

HachiyaKouya

総合スコア85

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ranran

2015/02/15 15:51

回答ありがとうございます。 スレッドセーフと排他制御、頭の中でこんがらがっているので調べてみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問