小智 136

不幸的是,每个人都错过了信号量和互斥量之间最重要的区别; " 所有权 " 的概念.

信号量没有所有权的概念,这意味着任何线程都可以释放信号量(这可能导致许多问题,但可以帮助"死亡检测").而互斥锁确实具有所有权的概念(即,您只能释放已获得的互斥锁).
对于并发系统的安全编程,所有权非常重要.我总是建议使用互斥量优先于信号量(但有性能影响).

互斥体还可以支持优先级继承(可以帮助解决优先级倒置问题)和递归(消除一种类型的死锁).

还应该指出,存在"二进制"信号量和"计数/一般"信号量.Java的信号量是一个计数信号量,因此允许用大于1的值初始化它(而如指出的那样,互斥量只能是一个概念计数).其他职位也指出了这方面的用处.

总而言之,除非你有多个资源需要管理,否则我总是会推荐信号量超过信号量.


Eri*_*ric 115

可以计算信号量,而互斥量只能计为1.

假设您正在运行一个接受客户端连接的线程.该线程可以同时处理10个客户端.然后每个新客户端设置信号量,直到它达到10.当信号量有10个标志,那么你的线程将不接受新的连接

互斥通常用于保护东西.假设您的10个客户端可以访问系统的多个部分.然后,您可以使用互斥锁保护系统的一部分,因此当1个客户端连接到该子系统时,没有其他人可以访问.您也可以使用信号量来实现此目的.互斥是一种"互斥信号量".

  • 这不是真的.同一个线程可以多次输入相同的互斥锁,因此需要维护一个计数以确保条目`和退出是平衡的. (3认同)
  • @ edA-qa mort-ora-y,Java VM或API规范中没有使用术语"Mutex",因此我假设它指的是内置于每个对象的监视器,这也类似于称为Mutex的Win32对象.这同样适用于"ReentrantLock".所有这些都是递归的.我不知道任何"真实世界"的非递归互斥体的例子(我只在教科书中看过它们)所以我没有考虑它们. (2认同)
  • 可以使用计数为1的信号量来实现非递归互斥锁.如果要阻止递归调用,这可能很有用.这有实际用途,我个人在大项目中使用它来检测初始化代码中的循环(A初始化B,试图再次初始化A). (2认同)

aJ.*_*aJ. 40

互斥基本上是互斥的.只有一个线程可以一次获取资源.当一个线程获取资源时,在拥有资源的线程释放之前,不允许其他线程获取资源.等待获取资源的所有线程都将被阻止.

信号量用于控制执行的线程数.将有固定的资源集.每当线程拥有相同的资源时,资源计数就会减少.当信号量计数达到0时,则不允许其他线程获取资源.线程被阻塞,直到其他线程拥有资源释放.

简而言之,主要区别在于允许一次获取资源的线程数量多少?

  • 互斥 - 一个.
  • 信号量 - 它的DEFINED_COUNT,(与信号量一样多)


Jas*_*oco 8

互斥锁用于对资源进行串行访问,而信号量则限制对资源的访问,直到达到设定的数量.您可以将互斥锁视为访问计数为1的信号量.无论您将信号量计数设置为什么,线程都可以在资源被阻止之前访问资源.