• ベストアンサー

マルチスレッドと変数

マルチスレッドのプログラムを組んでいます。 そこで、複数のスレッドからアクセスする変数があるのですが、これの扱いについて解らないことがあります。 ・変数を複数のスレッドから書き換える場合は、予想していた結果と違うことになる。 ここまではいいのですが、 ・変数を複数のスレッドから、参照だけするのは問題ない。 ・変数を複数のスレッドから、参照し、書き換えるのはひとつのスレッドだけならば、問題はない。 (上の"変数"は全て、Lockをかけていない状態です。) という認識をもっているのですが、これは間違いなのでしょうか? 「参照だけならばLockはかけなくてよい」というのをどこかで読んだような覚えがあり、そのまま勝手に最後の推測をしています。 現状ではうまくいっているようなのですが、とても不安です。 もしくは、状況、環境、コーディングによって上の仮定は成立したり、成立しなかったりするのでしょうか?環境はC#ですが、もしどのような言語、環境であっても一般的に、同じような結果になるのなら、それも合わせてご教授お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.4

ANo.3の補足の件。 long型(64ビット)だと、32ビットCPUでは一命令でアクセスできずに上位ワードと下位ワードの2回に分けてアクセスするため、その間に別スレッドからの書き換えが割り込むと拙いからです。 2ワードのアクセスの間に他スレッドからの書き換えが起きないことをロック以外の方法で保証できるなら読み込みロックは必要ありません。 なお、レジスタワード長が16ビット以下のCPUでは32ビット変数の一命令アクセスができないので、32ビット変数でも同様に複数スレッド間での排他処理が必要です。 # 16ビットCPUといってもレジスタワード長は32ビットのものも多いけど

qOat
質問者

お礼

丁寧な回答ありがとうございます。 とてもためになりました。

その他の回答 (3)

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.3

変数がint型のような単純な整数変数なら読み出しはロックなしで問題ありません。 しかし、long型(64ビット)やクラス型のオブジェクトだと、一回の処理で読み出しができないため、読み出し途中に書き換えられて異常な値を読む恐れがあります。 たとえば、マウスの座標(x,y)を読むことを考えましょう。始めの座標は(0,0)で、読み出しスレッドがx座標を読んでからy座標を読むまでに座標が(100,100)に書き換えられると、読み出しスレッドは書き換え前とも書き換え後とも違う座標(0,100)を読むことになります。 このように途中で別スレッドが割り込む可能性がある読み出しではロックが必要になります。

qOat
質問者

お礼

回答ありがとうございます。 そうなんですよね。単体のフィールドならば、問題ないと思うのですけど、複数あって意味のあるものだと、単に読んでしまうと、rinkunさんのおっしゃるようなことが起こりえますよね。 十分留意していきたいと思います。

qOat
質問者

補足

すいません。質問です。 クラスのインスタンスだと、フィールドが複数読む場合に問題があるのはわかるのですが、longでも問題になるのは、alignなどの問題のためでしょうか?それとも、他の問題なのでしょうか?

回答No.2

したい処理によります。 いつ他のスレッドに切り替わるかは、プログラム作成者には分かりません。だから、いつも最悪のタイミングを想定してください。 データを参照したあと・かつ・そのデータを処理する前に他のスレッドによって変数が書き換えられることが考えられますよね。 片方の進捗状況を確認するだけなどのゆるい関係ならそれでも構わないと思います。 が、二カ所以上を参照していて、それらが同じタイミングでのデータであるという前提でプログラム組んだりするとまずいことになります。 ロック取得してその変数に関わる処理をし終えてからロック解放、が原則です。

qOat
質問者

お礼

やはり、安全第一にやるべきですよね。。。。 これからは、原則に忠実にロック、解放をしようと思います。

回答No.1

基本的にはその通りです。 ただし本当に読むだけならよいのですが、普通は読んでその結果によって何かしますよね。この後で「何かする時」に書き換えられていない、という保証はできませんので、場合によっては読むだけでも、その状態が必要な区間書き換えられないように変数をlockすることもあります。

qOat
質問者

お礼

なるほど。 やはり、基本は「Lock」なのですね。 参考になります。 返答ありがとうございます。

関連するQ&A

専門家に質問してみよう