C# lock Monitor Mutex SpinLock 区别

阅读更多

1、Mutex 互斥锁

 Mutex mut = new Mutex();
...
mut.WaitOne();
...
mut.ReleaseMutex();//释放锁

 只能有一个线程 进入执行逻辑

if (mut.WaitOne(1000)) {     //等待一个时间,超过时间将返回false    
           // Simulate some work.
           Thread.Sleep(5000);
           // Release the Mutex.
              mut.ReleaseMutex();
        }
        else {
           Console.WriteLine("{0} will not acquire the mutex", 
                             Thread.CurrentThread.Name);
        }

 上面的实例说明,当一个线程进入执行逻辑后,如果其他线程等待超时,将不再进入执行逻辑。

2、Monitor --只能加锁 引用类型对象

Random rnd = new Random();//定义一随机数生成对象
 Monitor.Enter(rnd);
   ...
 Monitor.Exit(rnd);

 当锁定一个值类型,会出现什么情况呢?每个任务都将引发 SynchronizationLockException 异常。如下代码所示

int nTasks = 0;
Monitor.Enter(nTasks);
 try {
    nTasks += 1;
  }
finally {
       Monitor.Exit(nTasks);
}

 原因:Monitor会对nTasks进行装箱,退出的时候将不再是同一个引用对象,所以会抛出异常。

以上的解决方法是,使用nTasks之前先进行装箱。

 int nTasks = 0;
 object o = nTasks;
  Monitor.Enter(o);
try {
   nTasks++;
  }
 finally {
 Monitor.Exit(o);
 }

 3、lock 关键字--底层由Monitor实现。

lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区。 如果其他线程尝试进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
lock 关键字在块的开始处调用 Enter,而在块的结尾处调用 Exit。 ThreadInterruptedException 引发,如果 Interrupt 中断等待输入 lock 语句的线程。
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。

常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:
如果实例可以被公共访问,将出现 lock (this) 问题。
如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。
由于进程中使用同一字符串的任何其他代码都将共享同一个锁,所以出现 lock("myLock") 问题。
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。
在 lock 语句的正文不能使用 等待 关键字。

Enter指的是Monitor.Enter(获取指定对象上的排他锁。),Exit指的是Monitor.Exit(释放指定对象上的排他锁。)

所以lock底层是Monitor实现的。

private static object objlock = new object();
lock (objlock )
{
    //要执行的代码逻辑
}

 4、SpinLock 是一种低级互斥锁,可用于等待时间非常短的方案。

如果锁住的逻辑执行时间很短,请使用spinlock,这样会获得比lock 更高的性能

 

SpinLock _spinlock = new SpinLock();
...
         bool lockTaken = false;
         try
         {
             _spinlock.Enter(ref lockTaken);
             ...;//执行时间短的逻辑                
         }
         finally
         { 
             if (lockTaken) _spinlock.Exit(false);
         } 

 在 SpinLock.Exit 调用中使用 false 这可提供最佳性能。true的话会启动异常跟踪

 

 

 

 

你可能感兴趣的:(lock,monitor,mutex,SpinLock)