ภาพรวม
Mutex (Mutual Exclusion) เป็น Synchronization Primitive ที่ทำงานข้าม Process ได้ (Cross-process) ใช้สำหรับป้องกันการเข้าถึงทรัพยากรร่วมกันระหว่าง Process หลายตัว
การสร้าง Mutex
using System;
using System.Threading;
// 1. Unnamed Mutex (Local to Process)
Mutex localMutex = new Mutex();
// 2. Named Mutex (Cross-Process)
Mutex namedMutex = new Mutex(false, "Global\\MyAppMutex");
// 3. Named Mutex with Initial Ownership
Mutex ownedMutex = new Mutex(true, "MyAppMutex", out bool createdNew);
พารามิเตอร์ Constructor
| Parameter | คำอธิบาย |
bool initiallyOwned | true = เธรดสร้างเป็น Owner ทันที, false = ไม่ได้เป็น Owner |
string name | ชื่อ Mutex (ใช้ Global\\ สำหรับ Cross-session, Local\\ สำหรับ Session เดียว) |
out bool createdNew | คืนค่า true ถ้าสร้างใหม่, false ถ้า Mutex ชื่อนี้มีอยู่แล้ว |
ตัวอย่าง: Single Instance Application
using System;
using System.Threading;
class Program {
static Mutex _mutex;
static void Main() {
bool createdNew;
_mutex = new Mutex(true, "Global\\MyUniqueAppId-{GUID}", out createdNew);
if (!createdNew) {
Console.WriteLine("Another instance is already running.");
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
return;
}
try {
Console.WriteLine("Application started. Press Enter to exit.");
Console.ReadLine();
}
finally {
_mutex.ReleaseMutex();
}
}
}
ตัวอย่าง: Interprocess Synchronization
// Process A (Writer)
using (var mutex = new Mutex(false, "Global\\SharedDataMutex")) {
mutex.WaitOne();
try {
// Write to shared memory / file
File.WriteAllText("shared.txt", DateTime.Now.ToString());
Console.WriteLine("Data written.");
}
finally {
mutex.ReleaseMutex();
}
}
// Process B (Reader)
using (var mutex = new Mutex(false, "Global\\SharedDataMutex")) {
mutex.WaitOne();
try {
string data = File.ReadAllText("shared.txt");
Console.WriteLine($"Data read: {data}");
}
finally {
mutex.ReleaseMutex();
}
}
Mutex vs Lock
| Feature | Mutex | lock (Monitor) |
| Cross-Process | Yes (Named) | No |
| Reentrant | No (Default) | Yes |
| Performance | Slower (Kernel Object) | Faster (User Mode) |
| Timeout | WaitOne(TimeSpan) | Monitor.TryEnter(TimeSpan) |
| Abandoned Mutex | Throw AbandonedMutexException | N/A |
Best Practices
- ใช้ชื่อ Unique (GUID) ป้องกันชื่อชน
- ใช้
Global\\ Prefix สำหรับ System-wide, Local\\ สำหรับ Session-wide
- ใช้
using Statement หรือ try/finally เพื่อ Release แน่ใจ
- จับ
AbandonedMutexException เมื่อ Owner Terminate โดยไม่ Release
- หลีกเลี่ยง Mutex สำหรับ In-process Synchronization (ใช้ lock/ReaderWriterLockSlim แทน)