VC.NET ~ Threading::Monitorクラス

本文

スレッド間の排他制御には、System.Threading::Monitorクラスを使います。Javaの、synchronizedブロックやObject#wait()、Object#notify()、Object#notifyAll()に相当する機能がサポートされています。

まず、単純な排他制御から。

// ロック生成。
Object^ theLock = gcnew Object();

// スレッドA上で。
Monitor::Enter(theLock);
try {
  doSomethingCritical(theLock);
}
finally {
  Monitor::Exit(theLock);
}

上記の排他制御中に、一時的にtheLockへのロックを解放して、他スレッド(スレッドB)の処理を待ちたい場合は、Monitor::Wait()を使います。

void doSomethingCritical(Object^ aLock) {
  runThreadB();
  doThis();
  Monitor::Wait(aLock);
  doThat();
}

一方スレッドBは、処理の完了をMonitor::Pulse()によってスレッドAに伝えます。

// スレッドB上で。
Monitor::Enter(theLock);
try {
  doSomethingForThreadA();
  Monitor::Pulse(theLock);
}
finally {
  Monitor::Exit(theLock);
}

スレッドAが、Monitor::Wait()から抜ける条件は、theLockに対するパルスを受け取り、かつtheLockへのロックを再獲得することです。doSomethingForThreadA()で例外が発生するとPulse()せずにtheLockを解放してしまうので、スレッドAはブロックされたままになります。Pulse()はfinallyブロックに移動した方が良いかもしれません(ケース・バイ・ケースですが)。

パルス待ちしているスレッドが複数ある場合でも、Pulse()がパルスを送るのは1スレッド宛てだけです。パルスをブロードキャストしたい場合は、Monitor::PulseAll()を使います。

Last modified:2012/05/08 18:58:41
Keyword(s):
References:[.NETアプリ開発]
This page is frozen.