有人能解释一下:
我就是想不明白,在我看来前两个是一样的?
问得好。也许我错了。.让我试试。.我的设计答案的第二修订版。.多一点理解。谢谢你让我读:)
Lock (obj)
监视器
使用锁或监视器有助于防止同时执行线程敏感的代码块,但是 这些结构不允许一个线程与另一个线程通信事件,这需要同步事件是有信号和无信号两种状态之一的对象,可用于激活和挂起线程。 互斥,信号量是操作系统级别的概念。例如,使用一个命名的互斥对象,您可以跨多个(受管理的)前端进行同步(确保您的应用程序只有一个实例在计算机上运行)
互斥:
信号灯伤害了我的大脑。
要读取的页面-线程同步(C #)
如 ECMA 中所述,从反射方法中可以观察到,lock 语句基本上等效于
object obj = x; System.Threading.Monitor.Enter(obj); try { … } finally { System.Threading.Monitor.Exit(obj); }
从上面的例子中,我们可以看到 Monitor 可以锁定对象。
当需要进程间同步时,Mutexe 很有用,因为它们 可以锁定字符串标识符。不同的进程可以使用相同的字符串标识符来获取锁。
信号量就像类固醇上的互斥体,它们通过提供最大的并发访问计数来允许并发访问。一旦达到限制,信号量就开始阻塞对资源的任何进一步访问,直到其中一个调用者释放信号量。
关于“使用其他.Net 同步类”——其他一些你应该知道的:
在 CCR/TPL (并行扩展 CTP)中还有更多(低开销)的锁定构造-但是 IIRC,这些将在。NET 4.0
对于用字符串 ID 标识的任何共享互斥锁的另一个警告是,它将默认为“ Local”互斥锁,并且不会在终端服务器环境中的会话间共享。
在字符串标识符前面加上“ Global”,以确保正确控制对共享系统资源的访问。在我意识到这一点之前,我刚刚遇到了一大堆的问题,这些问题是如何将通信同步到一个在 SYSTEM 帐户下运行的服务上的。
我会尽量避免“锁()”,“互斥”和“监视器”,如果你可以..。
查看.NET4中新的命名空间 System.Collections.Concurrent 它有一些很好的线程安全的集合类
Http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
并行字典加冰! 我再也不用手动锁定了!
我在 DotGNU 中做了类和 CLR 对线程的支持,我有一些想法..。
除非您需要跨进程锁,否则应该始终避免使用 Mutex & Semaphores。这些课程。NET 是围绕 Win32互斥和信号量的包装器,并且相当重量级(它们需要将上下文切换到内核,这是昂贵的——特别是如果您的锁不在争用范围之内)。
正如前面提到的,C # lock 语句是 Monitor 的编译魔术。输入并监视。退出(存在于 try/finally 中)。
显示器有一个简单但强大的信号/等待机制,互斥体没有通过显示器。脉搏/监视器。等待方法。Win32等价物是通过 CreateEvent 的事件对象,它实际上也存在于。作为 WaitHandles。Pulse/Wait 模型类似于 Unix 的 pthread _ information 和 pthread _ Wait,但是速度更快,因为它们在非竞争情况下可以完全是用户模式的操作。
监视器。脉搏/等待使用起来很简单。在一个线程中,我们锁定一个对象,检查标志/状态/属性,如果它不是我们所期望的,则调用 Monitor。等待,这将释放锁和等待,直到一个脉冲发送。当等待返回时,我们循环返回并再次检查标志/状态/属性。在另一个线程中,每当我们更改标志/状态/属性时,我们都会锁定该对象,然后调用 PulseAll 来唤醒任何侦听线程。
通常,我们希望类是线程安全的,所以我们在代码中加入了锁。但是,我们的类常常只被一个线程使用。这意味着锁不必要地降低了我们的代码速度... 这就是 CLR 中聪明的优化可以帮助提高性能的地方。
我不确定微软的锁的实现,但是在 DotGNU 和 Mono 中,锁状态标志存储在每个对象的头中。里面的所有东西。NET (和 Java)可以成为一个锁,所以每个对象都需要在它们的头部支持这一点。在 DotGNU 实现中,有一个标志允许您对每个用作锁的对象使用全局哈希表——这样做的好处是消除了每个对象的4字节开销。这对于内存来说不是很好(特别是对于没有大量线程的嵌入式系统) ,但是对性能有很大的影响。
Mono 和 DotGNU 都有效地使用互斥锁来执行锁定/等待,但是使用自旋锁样式的 比较与交换操作来消除实际执行硬锁定的需要,除非真的有必要:
您可以在这里看到如何实现监视器的一个示例:
Http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
在大多数情况下,不应该使用锁(= Monitor)或互斥量/信号量。它们都会在同步操作时阻塞等待的线程。因此,它们只适用于非常小的操作。
而且您肯定使用 不应该使用 System.Collections.Concurrent类-它们不支持具有多个集合的事务,并且还使用阻塞同步。
System.Collections.Concurrent
令人惊讶的是.NET 没有有效的非阻塞同步机制。
我在 C # 上从 GCD (Objc/Swift world)实现了 串行队列——非常轻量级,没有阻塞使用线程池的同步工具,带有测试。
Objc/Swift
在大多数情况下,这是同步任何事情的最佳方式——从数据库访问(hello sqlite)到业务逻辑。