首页 文章

C#中各种线程同步选项有什么区别?

提问于
浏览
153

有人可以解释之间的区别:

  • lock(someobject){}

  • 使用互斥锁

  • 使用信号量

  • 使用监视器

  • 使用其他.Net同步类

我只是想不出来 . 在我看来前两个是一样的?

6 回答

  • 12

    好问题 . 我可能错了..让我试试..我的原始答案的修订版#2 ......稍微有点理解 . 谢谢你让我读:)

    lock(obj)

    • 是一个CLR结构,用于(对象内?)线程同步 . 确保只有一个线程可以获取对象锁的所有权并输入锁定的代码块 . 其他线程必须等到当前所有者通过退出代码块放弃锁定 . 此外,建议您锁定类的私有成员对象 .

    Monitors

    • lock(obj)在内部使用Monitor实现 . 你应该更喜欢lock(obj),因为它可以防止你像忘记清理程序一样 . 它是'idiot-proof'的监视器构造,如果你愿意的话 .
      使用Monitor通常比互斥锁更受欢迎,因为监视器是专门为.NET Framework设计的,因此可以更好地利用资源 .

    使用锁或监视器对于防止同时执行线程敏感的代码块非常有用,但 these constructs do not allow one thread to communicate an event to another. This requires synchronization events 是具有两种状态之一(已发信号和未发出信号)的对象,可用于激活和挂起线程 . Mutex,Semaphores是操作系统级别的概念 . 例如,使用已命名的互斥锁,您可以跨多个(托管)exes进行同步(确保只有一个应用程序实例在计算机上运行 . )

    Mutex:

    • 与监视器不同, a mutex can be used to synchronize threads across processes. 当用于进程间同步时,互斥锁称为 named mutex ,因为它将在另一个应用程序中使用,因此无法通过全局变量或静态变量进行共享 . 必须为其指定名称,以便两个应用程序都可以访问相同的互斥对象 . 相比之下, the Mutex class is a wrapper to a Win32 construct. While it is more powerful than a monitor, a mutex requires interop transitions that are more computationally expensive than those required by the Monitor class.

    Semaphores (伤害了我的大脑) .

    • 使用Semaphore类来控制对资源池的访问 . 线程通过调用WaitOne方法进入信号量,该方法继承自WaitHandle类,并通过调用Release方法释放信号量 . 每次线程进入信号量时,信号量的计数递减,而当线程释放信号量时递增 . 当计数为零时,后续请求将阻塞,直到其他线程释放信号量 . 当所有线程都释放了信号量时,计数将达到创建信号量时指定的最大值 . A thread can enter the semaphore multiple times..The Semaphore class does not enforce thread identity on WaitOne or Release.. programmers responsibility to not muck up. 信号量有两种类型:本地信号量,名为 system semaphores. If you create a Semaphore object using a constructor that accepts a name, it is associated with an operating-system semaphore of that name. 命名系统信号量在整个操作系统中都可见,可用于同步进程的活动 . A local semaphore exists only within your process. It can be used by any thread in your process that has a reference to the local Semaphore object. Each Semaphore object is a separate local semaphore.

    THE PAGE TO READ - Thread Synchronization (C#)

  • 13

    重新“使用其他.Net同步类” - 您应该了解的其他一些:

    在CCR / TPL(Parallel Extensions CTP)中还有更多(低开销)锁定结构 - 但是IIRC,这些将在.NET 4.0中提供

  • 127

    正如ECMA中所述,正如您可以从Reflected方法中观察到的那样,lock语句基本上等同于

    object obj = x;
    System.Threading.Monitor.Enter(obj);
    try {
       …
    }
    finally {
       System.Threading.Monitor.Exit(obj);
    }
    

    从前面提到的例子中我们看到监视器可以锁定对象 .

    当您需要进程间同步时,Mutexe非常有用,因为它们可以锁定字符串标识符 . 不同进程可以使用相同的字符串标识符来获取锁 .

    信号量就像类固醇上的互斥体一样,它们通过提供最大数量的并发访问来实现并发访问 . 达到限制后,信号量开始阻止对资源的任何进一步访问,直到其中一个调用者释放信号量 .

  • 27

    我在DotGNU中为线程做了类和CLR支持,我有一些想法......

    除非您需要跨进程锁定,否则应始终避免使用互斥锁和信号量 . .NET中的这些类是Win32 Mutex和Semaphores的包装器,并且相当重要(它们需要上下文切换到内核,这是昂贵的 - 特别是如果您的锁不在争用) .

    正如其他人所提到的,C#lock语句是Monitor.Enter和Monitor.Exit的编译魔术(存在于try / finally中) .

    监视器有一个简单但功能强大的信号/等待机制,Mutexes没有通过Monitor.Pulse / Monitor.Wait方法 . Win32等价物将是通过CreateEvent的事件对象,它实际上也作为WaitHandles存在于.NET中 . Pulse / Wait模型类似于Unix的pthread_signal和pthread_wait,但速度更快,因为在非竞争情况下它们可以完全是用户模式操作 .

    Monitor.Pulse / Wait很简单易用 . 在一个线程中,我们锁定一个对象,检查一个标志/状态/属性,如果它不是我们所期望的,请调用Monitor.Wait,它将释放锁并等待直到发送一个脉冲 . 等待返回时,我们循环返回并再次检查flag / state / property . 在另一个线程中,每当我们更改flag / state / property然后调用PulseAll来唤醒任何侦听线程时,我们都会锁定对象 .

    通常我们希望我们的类是线程安全的,所以我们在我们的代码中放置了锁 . 但是,通常情况是我们的类只会被一个线程使用 . 这意味着锁会不必要地减慢我们的代码......这就是CLR中的巧妙优化可以帮助提高性能的地方 .

    我不确定微软的锁实现,但在DotGNU和Mono中,锁状态标志存储在每个对象的标头中 . .NET(和Java)中的每个对象都可以成为一个锁,因此每个对象都需要在其 Headers 中支持它 . 在DotGNU实现中,有一个标志允许您为每个用作锁的对象使用全局哈希表 - 这有利于消除每个对象的4字节开销 . 这对于内存来说并不是很好(特别是对于没有高度线程化的嵌入式系统)但是性能受到打击 .

    Mono和DotGNU都有效地使用互斥锁来执行锁定/等待,但使用自旋锁样式compare-and-exchange操作来消除实际执行硬锁的需要,除非确实需要:

    您可以在此处查看如何实现监视器的示例:

    http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup

  • 5

    锁定在您使用字符串ID标识的任何共享互斥锁上的另一个警告是它将默认为“本地”互斥锁,并且不会在终端服务器环境中的会话之间共享 .

    使用“Global \”作为字符串标识符的前缀,以确保正确控制对共享系统资源的访问 . 在我意识到这一点之前,我刚刚遇到了一大堆问题,这些问题与SYSTEM帐户下运行的服务同步通信 .

  • 9

    如果可以的话,我会尽量避免“锁定()”,“互斥”和“监视”......

    查看.NET 4中的新命名空间System.Collections.Concurrent
    它有一些很好的线程安全的集合类

    http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx

    ConcurrentDictionary摇滚!我不再手动锁定了!

相关问题