什么是Java中的互斥和信号量? 主要区别是什么?

什么是Java中的互斥和信号量? 主要区别是什么?

信号量可以被计数,而互斥量只能算到1。

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

互斥锁通常用于守卫东西。 假设你的10个客户端可以访问系统的多个部分。 然后你可以用一个互斥体来保护系统的一部分,所以当一个客户连接到这个子系统时,其他人都不应该访问。 你也可以为此使用信号量。 互斥体是一个“互斥信号量” 。

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

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

互斥体也可以支持优先级inheritance(可以帮助优先级反转问题)和recursion(消除一种types的死锁)。

还应该指出的是,有“二元”信号量和“计数/一般”信号量。 Java的信号量是一个计数信号量,因此可以用大于1的值进行初始化(然而,正如所指出的,一个互斥量只能是一个概念数)。 其他职位已经指出了这一点的用处。

所以总而言之,除非你有多个资源来pipe理,否则我总是会推荐信号量的互斥。

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

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

总之,主要的区别是有多less个线程可以同时获取资源?

  • 互斥 – 一个。
  • 信号量 – 它的DEFINED_COUNT(多达信号量)

互斥量用于对资源进行串行访问,而信号量限制对资源的访问,最多只能设置一个数量。 您可以将互斥量视为访问计数为1的信号量。无论您将信号计数设置为什么,线程可以在资源被阻止之前访问资源。

Feabhas的回答非常重要 – 互斥体检查试图释放互斥体的线程实际拥有它。 我把这个作为一个面试的问题,所以它值得记住。

一个信号量是一个计数同步机制,一个互斥量不是。

互斥体通常被称为二进制信号量。 虽然信号量可以用任何非零计数来创build,但互斥量在概念上是一个高位计数为1的semeaphore。

这个问题有相关的答案,并链接到官方的Java指导:Java中是否存在Mutex?

你比较无与伦比,从技术上说,信号量和互斥量没有区别,这是没有意义的。 互斥量它只是一个重要的名字,就像你的应用程序逻辑中的任何名字一样,这意味着你初始化一个信号量为“1”,它通常用来保护一个资源或一个受保护的variables,以确保相互排斥。

互斥是二进制信号量。 必须用1来初始化,以达到先到先得的原则。 这就把我们带到了每个互斥体的另一个特殊的属性上: 那个倒下的人 ,一定是那个倒下的人 。 我们已经获得了一些资源的相互排斥。

现在你可以看到互斥量是一般信号量的特例。

同步Semaphore的目的是实现一个经典的交通灯。 红绿灯控制对柜台共享资源的访问。 如果计数器大于零,则授予访问权限; 如果它是零,访问被拒绝。 计数器计算允许访问共享资源的权限。 然后,要访问资源,一个线程必须获得交通信号灯的许可。 一般来说,要使用红绿灯,想要访问共享资源的线程会尝试获取许可证。 如果信号灯数量大于零,则线程获取许可证,并且交通信号灯计数递减。 否则,线程将被locking,直到获得许可。 当线程不再需要访问共享资源时,它释放权限,所以交通灯数量增加。 如果有另外一个线程在等待许可证,那么当时就会获得许可证。 Java的Semaphore类实现了这个机制。

信号量有两个build造者:

 Semaphore(int num) Semaphore(int num, boolean come) 

num指定许可证的初始计数。 然后num指定在给定时间可以访问共享资源的线程数。 如果num是1,则一次只能访问一个线程的资源。 通过设置为true,可以保证您所等待的线程按照他们请求的顺序被授予权限。

信号量 :

计数信号量 从概念上讲,信号量拥有一套许可证。 如果需要,每个acquire()阻塞,直到获得许可证为止,然后将其获取。 每个release()添加一个许可证,可能会释放一个阻止的获取者。 但是,没有使用实际的许可证对象; 信号只是保持可用数量的计数,并采取相应的行动。

信号量通常用于限制线程数量,而不是访问某些(物理或逻辑)资源

Java没有内置的Mutex API。 但它可以实现为二进制信号量。

一个信号量被初始化为1,并且被使用,使得它最多只有一个可用的许可证,可以作为互斥锁。 这通常被称为二进制信号量,因为它只有两个状态:一个允许可用,或者零允许可用。

当以这种方式使用时,二进制信号量具有属性(与许多Lock实现不同), “锁”可以由所有者以外的线程释放(因为信号量没有所有权概念) 。 这在一些特定的上下文中是有用的,比如死锁恢复。

所以Semaphore和Mutex之间的主要区别是:

  1. 信号量限制线程访问资源通过许可。 互斥体只允许一个线程访问资源。

  2. 没有线程拥有信号量。 线程可以通过调用acquire()release()方法来更新许可证的数量。 互斥锁只能由持锁的线程解锁。

  3. 当一个互斥体与条件variables一起使用时,隐含的包围就是明确的它清楚程序的哪一部分正在被保护 。 这不一定是信号量的情况,这可能被称为并发编程 – 它是强大的,但非常容易以非结构化,不确定的方式使用。