`
wyf
  • 浏览: 437919 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

C# lock Monitor Mutex SpinLock 区别

    博客分类:
  • C#
阅读更多

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的话会启动异常跟踪

 

 

 

 

分享到:
评论

相关推荐

    C#各种多线程使用的示例

    使用`SpinLock.Lock()`获取锁,`SpinLock.Unlock()`释放。 3. **线程同步方法** - **Mutex.WaitOne() 和 Mutex.ReleaseMutex()**:用于在多线程环境中同步对共享资源的访问。 - **Monitor.Enter() 和 Monitor....

    ThreadLocked多线程共享资源

    在C#中,主要的线程锁包括`lock`语句、`Monitor`类、`Mutex`、`Semaphore`和`SpinLock`等。 二、`lock`语句 `lock`是C#中实现互斥访问的最简单方式。它基于`Monitor`类,确保同一时刻只有一个线程可以执行锁定的...

    进制运行两个应用程序(C#源码)

    C#提供了多种并发控制结构,如锁(`lock`关键字)、 Monitor、Mutex、Semaphore 和 SpinLock等。同时,`async/await`关键字可以用于实现异步编程,提高性能。 4. **禁止运行**:标签中的“禁止”可能是指在某些情况...

    C#并发编程经典实例 源码

    为避免这种情况,C#提供了多种同步机制,如`Monitor`、`Mutex`、`Semaphore`和`SpinLock`等。 3. **锁机制**:`lock`关键字是C#中最简单的同步原语,它基于`Monitor`类实现。它用于确保一次只有一个线程执行特定...

    C#线程控制

    当需要在多个线程间同步时,可以使用Monitor、Mutex、Semaphore、SpinLock等同步原语,防止数据竞争和其他并发问题。例如,Monitor类提供了Enter和Exit方法,用于实现临界区(Critical Section): ```csharp ...

    胡侃软件开发之C#的线程

    Lock锁是C#提供的一个同步原语,通过lock关键字,可以确保同一时刻只有一个线程能执行指定的代码块,这通常用于同步访问资源,防止竞态条件。 Monitor锁是.NET中管理线程同步访问资源的一种机制,它使用Enter和Exit...

    在C#中实现线程安全消息队列

    在C#中,可以使用Monitor、Mutex、Semaphore、SpinLock等类来控制对共享资源的访问。例如,当一个线程正在读取或写入消息时,其他线程应该被阻止执行相同的操作。 2. **线程间通信**:.NET框架提供了许多用于线程间...

    C#线程同步的三类情景分析

    4. **SpinLock**:轻量级锁,适用于短时间的同步,避免了 Monitor 的上下文切换开销。 5. **ReadWriteLockSlim**:读写锁,允许多个读线程并行访问,但写线程独占资源。 6. **Mutex**:全局互斥锁,不仅在进程内有效...

    SystemProgParallel

    4. **同步机制**:包括锁(`lock`关键字)、 Monitor、Mutex、Semaphore 和 SpinLock 等,用于控制并发访问共享资源时的同步问题,防止数据竞争。 5. **异步编程**:C#的`async`和`await`关键字使得异步编程更加...

    concurrencia

    C#提供了一些同步原语,如Monitor、Mutex、Semaphore和SpinLock,用于控制对共享资源的访问。此外,锁定语句(lock)和volatile关键字也是确保数据一致性的重要工具。 5. **并发集合**:System.Collections....

    VitruviSoft.Task

    5. **并发控制**:为了防止竞态条件和死锁,VitruviSoft.Task 可能包含了同步原语,如 `lock` 语句,`Monitor`, `Mutex`, `Semaphore`, 或 `SpinLock`,用于在多线程环境中协调访问共享资源。 6. **任务组合**:`...

    Managed threading.pdf

    - **锁机制**:通过`lock`关键字或`Monitor`类来实现锁。 - **读写锁**:使用`ReaderWriterLockSlim`类实现读写锁,允许多个读操作同时进行,但只允许一个写操作。 #### 5. 前台线程与后台线程(Foreground and ...

Global site tag (gtag.js) - Google Analytics