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

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

106961 次浏览

信号量是计数同步机制,互斥对象不是。

互斥体用于对资源的串行访问,而信号量将对资源的访问限制为一个设定的数字。您可以将互斥对象看作是访问计数为1的信号量。无论您将信号量计数设置为什么,线程都可以在阻塞资源之前访问该资源。

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

Suppose you have a thread running which accepts client connections. This thread can handle 10 clients simultaneously. Then each new client sets the semaphore until it reaches 10. When the Semaphore has 10 flags, then your thread won't accept new connections

Mutex are usually used for guarding stuff. Suppose your 10 clients can access multiple parts of the system. Then you can protect a part of the system with a mutex so when 1 client is connected to that sub-system, no one else should have access. You can use a Semaphore for this purpose too. A mutex is a "Mutual Exclusion Semaphore".

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

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

In short, the main difference is 允许多少个线程同时获取资源?

  • 互斥系统,一号。
  • 信号量——它的 DEFINED _ COUNT,(与信号量计数一样多)

互斥量通常被称为二进制信号量。虽然信号量可以用任何非零计数创建,但互斥量在概念上是一个信号量,其上限为1。

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

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

互斥对象也可以支持优先级继承(可以帮助解决优先转置问题)和递归(消除一种死锁)。

还应该指出,存在“二进制”信号量和“计数/一般”信号量。Java 的信号量是一个计数信号量,因此允许用大于1的值进行初始化(而正如前面指出的,互斥对象只能从概念上计数1)。其他文章也指出了这种方法的有用性。

因此,总结一下,除非您要管理多个资源,否则我总是建议使用互斥量而不是信号量。

你比较无与伦比的,技术上没有区别之间的信号量和互斥它没有意义。 Mutex 只是一个重要的名字,就像你的应用逻辑中的任何名字一样,它意味着你在“1”初始化一个信号量,它通常用于保护一个资源或受保护的变量,以确保互斥锁。

互斥是二进制信号量。它必须用1进行初始化,以满足先到先得的原则。这就引出了每个互斥对象的另一个特殊属性: 那个做到了“强”下来的人,一定是做到了“强”上来的人 。因此我们获得了一些资源的互斥锁。

Now you could see that a mutex is a special case of general semaphore.

同步 信号灯的对象实现了一个经典的交通灯。交通灯控制对计数器共享的资源的访问。如果计数器大于零,则授予访问权限; 如果为零,则拒绝访问权限。计数器计算允许访问共享资源的权限。然后,为了访问资源,线程必须接收来自交通灯的权限。通常,要使用红绿灯,想要访问共享资源的线程会尝试获取许可。如果交通灯数量大于零,则线程获得许可,并且交通灯数量减少。否则,线程将被锁定,直到获得权限为止。当线程不再需要访问共享资源时,它释放权限,从而增加交通灯数量。如果有另一个线程正在等待许可,它将在那个时候获得许可。Java 的 Semaphore 类实现了这种机制。

Semaphore 有两个建造者:

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

num specifies the initial count of the permit. Then num specifies the number of threads that can access a shared resource at a given time. If num is one, it can access the resource one thread at a time. By setting as true, you can guarantee that the threads you are waiting for are granted permission in the order they requested.

信号灯 :

一个计数信号灯。从概念上讲,信号量维护一组许可。如果需要,每个 acquire()都会阻止,直到获得许可证,然后再使用它。每个 release()添加一个许可,可能释放一个阻塞获取者。但是,没有使用实际的许可证对象; 信号量只是保持可用数量的计数并相应地执行操作。

Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource

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

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

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

所以 关键差异在 Semaphore 和 Mutex 之间:

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

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

  3. 当互斥对象与条件变量一起使用时,有一个隐含的括号ーー显然是 程序的哪一部分被保护了d。信号量可能被称为 进行并发编程,它的功能很强大,但是很容易以非结构化的、不确定的方式使用。