セマフォの基本的な質問なのですが、intのグローバル変数Xを

タスクAで読み書き、タスクBがそれを読むとします。
この時、双方のタスクでセマフォでの保護は必要でしょうか?
(タスクBは、読むだけです)
(OSは、Winに限定しません)

回答の条件
  • 1人2回まで
  • 登録:2009/09/03 10:03:43
  • 終了:2009/09/03 15:51:52

ベストアンサー

id:tdoi No.1

tdoi回答回数174ベストアンサー獲得回数752009/09/03 13:16:10

ポイント60pt

Producer-Consumer問題を念頭にしているのかと最初は思ったのですが、その状況とは違うということでいいのですよね?

話が抽象的で実現したいことは正確には分からないですが、質問に書いてあることだけから判断するのであれば、タスクAでの処理は排他制御する必要がある場合も、ない場合もあると思います。

例えば、タスクBにおいて、変数Xが最新の値を必ず取得する必要があるのであれば、何らかの仕組みで、排他制御をしないといけないでしょう。

逆に、1つ前の状態の値などでもよい、複数回同じ値を読んでもよいのであれば、そもそも排他制御する必要はないでしょう。

ただし、変数がアトミックな命令で割り当てられないのであれば、排他制御しないと問題になります。

例えばですが、C++でプログラムを書いていて、

X = new SomeClass();

のようなグローバル変数を扱うのであれば、排他制御しないと、オブジェクトが中途半端に構築された状態で、タスクBからアクセスされることとなり、問題になります。


何かの参考になれば。

id:suzume_oyado

ありがとうございます!

えと、例えば タスクAからタスクB内のループを終了させたいので

変数Xに 999を入れたいのです。

タスクBは、ループ内で変数Xを監視して 999が入ってたら終了します。

この時、セマフォで保護しないと 999を代入している間に

中途半端な状態で、タスクBが変数を読んでしまわないか?

という心配ですが、どうでしょう???

(このケースでは、中途半端な数字になっても問題はありませんが)

イベントフラグを使うのが正しいのかもしれませんが、セマフォのお勉強という意味で。

2009/09/03 13:35:42
  • id:tdoi
    まず、intであれば、中途半端な状態にはならないはずです。

    そして、その利用方法だとセマフォはいらないと思います。
    例外があるとすると、タスクAがタスクBを複数回実行する可能性があって、タスクBがXを確認して終了する前に次の実行をしようとしてXを別な値に書き換えたりするケースはまずいとは思いますが。

    2つのことを混同しているのだと思うのですが、
    セマフォを利用して実現することの排他制御としては、2つのレベルがあって、

    1つは、変数Xそのものの状態の不整合
    もう1つが、アプリケーションロジックとしての不整合

    です。

    変数Xについては、int型であるのであれば、アセンブラレベルまで落として考えれば、set系の1命令で実行されるので、Xそのものが不整合はありません。

    なので、ロジックとしての不整合がなければ、セマフォで排他制御を行う必要はないです。
  • id:suzume_oyado
    >変数Xについては、int型であるのであれば、アセンブラレベルまで落として考えれば、set系の1命令で実行されるので、Xそのものが不整合はありません。

    なるほど!
    ここが気になっていました。

    セマフォで囲まずに 実装したらすごく怒られたので 気になっていました。
    ありがとうございました!!
  • id:m_nagase
    すでに質問が終了しているのでコメントで補足しておきます。

    複数タスク間でグローバル変数を扱う場合、上記のように読み書きが一方方向でその処理を行っている最中にタスクスイッチが起きない事が保証されているのであれば排他制御は必要ありませんが、コンパイラなどで最適化されないように(レジスタ変数などの割り当てを抑制)する必要があります。C/C++であれば そのグローバル変数に対して volatile 宣言をしておいた方が良いと思われます。

    http://www.wdic.org/w/TECH/volatile

    volatile宣言することで、当該コード(タスクB)外でグローバル変数が書き換えられる可能性があるため、コンパイラはそのグローバル変数を参照するごとにメモリからデータを読み込むようにコンパイルされます。
  • id:pyopyopyo
    volatile だけでは不十分です。

    volatile はコンパイラの最適化に起因する問題が回避できるだけで、
    メモリバリアの問題を回避することが出来ません。良くある誤解ですので、気をつけましょう。

    http://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E3%83%AA%E3%83%90%E3%83%AA%E3%82%A2
  • id:suzume_oyado
    みなさん、コメントありがとうございます!
    えーと、よくわからなくなってきたのですが
    結局、「セマフォは必要」なのかな・・・(?_?)
  • id:tdoi
    レジスタ割り当てや、メモリバリアの話も重要で難しい話ですが、
    このケースでは、タスクBがそれ以降のタイミングで変数Xを見て終了しても構わないようなので、
    そこまで気にする必要はないのかなと思いますが、何か見落としていますでしょうか?

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません