大家有兴趣可以加我QQ群交流:14792063 广州软件开发团队
先来看一段我们多线程编程时常用的lock关键字程序片段
lock(obj)
{
// Do sth1
// Do sth2
}
{
// Do sth1
// Do sth2
}
知道lock工作原理的人都知道,他的实质其实等于
Monitor.Enter(obj); //acquire lock on object
// Do sth1
// Do sth2
Monitor.Exit(obj); //release lock
// Do sth1
// Do sth2
Monitor.Exit(obj); //release lock
不过这样会有一个潜在的问题:
如果在Do sth1,Do sth2中某处抛出了exception,那就会有大问题了,
Monitor.Exit(obj);这一语句不会执行,obj将继续保持lock状态永远得不到解锁。
解决这个和异常有关的问题,很自然可以想到finally语句:
Monitor.Enter(obj);
try
{
// Do sth1
// Do sth2
}
catch
{
}
finally
{
Monitor.Exit(obj);
}
try
{
// Do sth1
// Do sth2
}
catch
{
}
finally
{
Monitor.Exit(obj);
}
问题解决了,不过try/catch/finally代码段写起来很麻烦,看起来也不爽,想到C#里有个和finally作用差不多的关键字using,它在中间语句发生异常时也能析构对象,而且使用起来简约、整洁
using(obj)
{
}
{
}
不过using使用有一个前提,那就是这里的obj必须要继承IDispose接口,接下来就要引出本文的终极解决方案了,那就是设计一个类来实现这些工作,设置一个obj来接收要锁定的对象,这个类在初始化时Monitor.Enter(obj);在实现IDispose接口的Dispose()里Monitor.Exit(obj);然后在using语句中使用这个类的对象
下面看看ThreadLock这个类
代码
using System;
namespace MyThread
{
public class ThreadLock : IDisposable
{
private object objLock;
public ThreadLock()
{
}
//这里弄一个静态方法,为了使用方便
public static ThreadLock Lock(object objLock)
{
return new ThreadLock(objLock); 软件开发网
}
public ThreadLock(object objLock)
{
this.objLock = objLock;
Monitor.Enter(objLock);
}
public void Dispose()
{
Monitor.Exit(objLock);
}
}
}
namespace MyThread
{
public class ThreadLock : IDisposable
{
private object objLock;
public ThreadLock()
{
}
//这里弄一个静态方法,为了使用方便
public static ThreadLock Lock(object objLock)
{
return new ThreadLock(objLock); 软件开发网
}
public ThreadLock(object objLock)
{
this.objLock = objLock;
Monitor.Enter(objLock);
}
public void Dispose()
{
Monitor.Exit(objLock);
}
}
}
有了上面这个类,使用起来就很简单了
using (ThreadLock.Lock(obj))
{
// Do sth1
// Do sth2
}
{
// Do sth1
// Do sth2
}