C#のMonitorクラスとlockステートメントの違いを徹底解説
C#において、Monitorクラスとlockステートメントは、どちらもオブジェクトへのアクセスを同期させるための仕組みを提供します。実は、lockステートメントは「Monitor.Enter」をtry-finallyブロックで囲んだ構文のショートカット(糖衣構文)にすぎません。
lockとMonitorの使い分け
lockステートメントは簡潔に書けるため、基本的な排他制御には最適な選択肢です。一方、より高度なマルチスレッド処理を実装したい場合には、Monitorクラスが適しています。Monitorクラスを使うと、以下のようなメソッドを利用でき、きめ細かな制御が可能になります。
- TryEnter():ロックの取得を試み、取得できない場合でもブロックせずに処理を続行できる
- Wait():現在のロックを一時的に解放し、他のスレッドに譲る
- Pulse() / PulseAll():待機中のスレッドに再開を通知する
lockステートメントの使用例
次のコードは、lockステートメントを使って共有変数へのアクセスを同期させる基本的な例です。
class Program{
static object _lock = new object();
static int Total;
public static void Main(){
AddOneHundredLock();
Console.ReadLine();
}
public static void AddOneHundredLock(){
for (int i = 1; i <= 100; i++){
lock (_lock){
Total++;
}
}
}
}lockブロック内の処理は、例外が発生した場合でも自動的にロックが解放されるため、安全で簡潔に記述できます。
Monitorクラスの使用例
同じ処理をMonitorクラスで書くと、次のようになります。lockステートメントの内部では、まさにこのようなコードが生成されています。
class Program{
static object _lock = new object();
static int Total;
public static void Main(){
AddOneHundredMonitor();
Console.ReadLine();
}
public static void AddOneHundredMonitor(){
for (int i = 1; i <= 100; i++){
Monitor.Enter(_lock);
try{
Total++;
}
finally{
Monitor.Exit(_lock);
}
}
}
}このように、Monitor.Enterでロックを取得し、finallyブロック内でMonitor.Exitを呼び出すことで、例外発生時にも確実にロックを解放しています。
まとめ
| 項目 | lock | Monitor |
|---|---|---|
| 記述の簡潔さ | ◎ 短く書ける | △ コードが長くなる |
| 高度な制御(Wait/Pulse等) | × 不可 | ○ 可能 |
| タイムアウト付きロック取得 | × 不可 | ○ TryEnterで可能 |
単純な排他制御であればlockステートメントで十分ですが、スレッド間の待機・通知やタイムアウト制御など、高度な同期処理が必要な場面ではMonitorクラスを直接使用しましょう。
-
DirectX11とDirectX12の違いを徹底解説!ゲーマーが知っておくべきポイント
DirectXは、ソフトウェアがマルチメディアコンテンツを描画し、グラフィックハードウェアと通信するために使用されるAPI(アプリケーションプログラミングインターフェース)のコレクションです。DirectXの主要な構成要素であるDirect3Dは、ソフトウェアとグラフィックスハードウェア間の通信を担っています。ハードウェアは製品ごとに異なるため、標準化された関数や呼び出しのライブラリを通じてグラフィックカードと通信することで、ゲーム開発を大幅にスピードアップできます。これは「ハードウェア抽象化」と呼ばれ、APIの最も重要な役割となっています。車に例えてみましょう。1台の車の運転ができれば、ほぼ
-
C#の配列とリスト(List)の違いとは?特徴と基本的な使い方を解説
C#における配列(Array)とリスト(List<T>)は、どちらも複数のデータをまとめて扱うためのコレクションですが、その性質には重要な違いがあります。 配列とリストの主な違い 配列は、生成時にサイズが固定される、同じ型の要素を順番に格納するコレクションです。一度作成した後は要素数を変更できません。 一方、Listはジェネリックコレクションであり、要素の追加や削除に応じてサイズが自動的に拡張・縮小します。この柔軟性が最大の特徴です。 項目配列List<T> サイズ固定可変(動的) 要素の追加不可(再作成が必要)Addメソッドで可能 宣言方法型[] 変数名Lis