背景:同时开启两个线程调用同一函数,使用Mutex来保证一个线程独占一个资源的访问。因为某些需求,临时abort了thread1 ,这时程序报错,—出现被放弃的mutex
static Mutex mutex;
static Thread thread1, thread2;
static void Main(string[] args)
{
Create a new Mutex. The creating thread does not own the mutex.
mutex = new Mutex();
thread1 = new Thread(new ThreadStart(Func));
thread2 = new Thread(new ThreadStart(Func));
thread1.Start();
thread2.Start();
}
private static void Func()
{
mutex.WaitOne();
//do something
mutex.ReleaseMutex();
}
分析:
- thread1 被abort时,有可能正在执行do something的操作,所以终止线程时,因为占有Mutex 对象后,并没有释放它,这是thread2调用mutex.WaitOne();就会报错,提示出现被放弃的mutex,这是严重的编程错误,引发 AbandonedMutexException。
- 修改函数,并且不再终止thread1 线程。
private static void Func()
{
for (int i = 0; i < 3; i++)
{
mutex.WaitOne();
//do something
}
mutex.ReleaseMutex();
}
这时,thread1 执行完后,thread2执行报错。
1)为什么thread1 执行时,调用了3次mutex.WaitOne();没有报错呢?因为thread1 执行时,系统检查发现mutex时被当前线程占用,就直接返回了。换言之,waitOne是获取Mutex锁的方式,所以没有报错。
2)为什么thread2执行会报错?thread1 对锁会执行3次获取,但是在在线程结束时,只释放了一次,这样等另一个线程调用锁时,发现被一个结束的线程独占着,就会报错了。
2)如果调用1次mutex.WaitOne();两次ReleaseMutex 那么由于当前线程实际上是不占有锁的 那么会抛出异常。