スレッドでの排他処理について

[戻る]
上田 2011/05/30(月) 15:50:28
初心者的な質問で申し訳ありませんが、よろしくお願いします。
AとBのメソッドがあり、複数のスレッドで非同期的にメソッドが呼ばれています。
AとAが同時に呼ばれるときに排他処理をする必要は無いのですが、AとBが同時に呼ばれては
いけないので、排他処理をする必要があります。
この場合、一般的にはどのように排他すればよいのでしょうか?
Windows環境でWin32APIを使用しています。

仲澤@失業者 2011/05/30(月) 17:08:35
同一プロセス内のスレッド間の排他処理には
 1.クリティカルセクションで排他処理をする
 2.volatileなフラグで排他処理する
等が、すぐに思いつく方法です。

tetrapod 2011/05/30(月) 17:08:42
排他制御をどう実装すべきかは、案件(仕様)次第。
後から実行しようとしたほうが待てばいいのか、
優先順をつけて、優先側だけが実行される(非優先側が待つ)のか、
どっちかが待つことでデッドロックになったりしないか、
どのくらいの頻度で呼ばれるのか、
どのくらいのCPU負荷が許されるのか、
などなど考えるべき前提条件はみな違う。だから一般解ってのは無い。

とりあえず CriticalSection で実装するとしたら
EnterCriticalSection LeaveCriticalSection TryEnterCriticalSection
あたりを参照。

ITO 2011/05/31(火) 11:00:32
> AとBのメソッドがあり、複数のスレッドで非同期的にメソッドが呼ばれています。
うーーん、
  まず、完全でなくても同期的に呼ぶようにしたほうがいいですね。
 僕の場合、
  「CreateEvent()」,「WaitForSingleObjct()」を使って
 ある条件の時に制御を開始するようにして、理論上 AとBのメソッドが同時に
 呼ばれないようにしていますね。
  そのあと、中澤さん・tetrapodさんの意見どおり、リティカルセクション
 を使うのがいいと思います。
 ただ、条件によってはほかの排他処理が必要な場合もあります。
  WINDOWS 同期オブジェクトでぐぐるといいと思います。
 

ITO 2011/06/01(水) 13:53:55
うーーん
条件→状況ですね。
失礼しました。

浩二 2011/06/13(月) 01:39:46
無理矢理ですが、、

c はクリティカルセクションです。
g_a, g_b の読み書きには、 c 以外のクリティカルセクションで排他処理を。

volatile int g_a = 0; // A()を実行しているスレッド数
volatile int g_b = 0; // B()を実行しているスレッド数

A()
{
  EnterCriticalSection(c)

  g_b が 0 になるまで待機
  
  g_a++;

  LeaveCriticalSection(c);

    :
  A()の処理
    :

  g_a--;  
}


B()
{
  EnterCriticalSection(c)

  g_a が 0 になるまで待機
  Bが同時に呼ばれて困る場合は g_b も 0 になるまで待機
  
  g_b++;

  LeaveCriticalSection(c)
  
    :
  B()の処理
    :

  g_b--;  
}

古いスレッドには追加発言できません。