在使用多线程开发时,存在一定的共用数据,为了避免多线程同时操作同一数据,.NET提供了lock、Monitor、Interlocked等多个锁定数据的方式。
lock
lock的使用比较简单,如果需要锁定某个对象时,可以直接使用lock(this)的方式。
1 private void Method()
2 {
3 lock(this)
4 {
5 //在此进行的操作能保证在同一时间内只有一个线程对此对象操作
6 }
7 }
如果操作只锁定某段代码,可以事先建立一个object对象,并对此对象进行操作锁定,这也是.net提倡的锁定用法。
class Control
{
private object obj=new object();
public void Method()
{
lock(obj)
{.......}
}
}
Montior
Montior存在于System.Thread命名空间内,相比lock,Montior使用更灵活。
它存在 Enter, Exit 两个方法,它可以对对象进行锁定与解锁,比lock使用更灵活。
1 class Control
2 {
3 private object obj=new object();
4
5 public void Method()
6 {
7 Monitor.Enter(obj);
8 try
9 {......}
10 catch(Excetion ex)
11 {......}
12 finally
13 {
14 Monitor.Exit(obj);
15 }
16 }
17 }
18
使用try的方式,能确保程序不会因死锁而释放出异常!
而且在finally中释放obj对象能够确保无论是否出现死锁状态,系统都会释放obj对象。
而且Monitor中还存在Wait方法可以让线程等待一段时间,然后在完成时使用Pulse、PulseAll等方法通知等待线程。
Interlocked
Interlocked存在于System.Thread命名空间内,它的操作比Monitor使用更简单。
它存在CompareExchange、Decrement、Exchange、Increment等常用方法让参数在安全的情况进行数据交换。
Increment、Decrement 可以使参数安全地加1或减1并返回递增后的新值。
class Example
{
private int a=1;
public void AddOne()
{
int newA=Interlocked.Increment(ref a);
}
}
Exchange可以安全地变量赋值。
1 public void SetData()
2 {
3 Interlocked.Exchange(ref a,100);
4 }
CompareExchange使用特别方便,它相当于if的用法,当a等于1时,则把100赋值给a。
public void CompareAndExchange()
{
Interlocked.CompareExchange(ref a,100,1);
}