1. Overview
1.概述
In this tutorial, we’ll explore binary semaphores and reentrant locks. Also, we’ll compare them against each other to see which one is best suited in common situations.
在本教程中,我们将探讨二元信号和可重入锁。此外,我们还将对它们进行相互比较,看看在常见的情况下哪一种最适合。
2. What Is a Binary Semaphore?
2.什么是二进制语义词?
A binary semaphore provides a signaling mechanism over the access of a single resource. In other words, a binary semaphore provides a mutual exclusion that allows only one thread to access a critical section at a time.
二进制semaphore提供了一个关于单个资源访问的信号机制。换句话说,一个二进制semaphore提供了一个相互排斥的机制,每次只允许一个线程访问一个关键部分。
For that, it keeps only one permit available for access. Hence, a binary semaphore has only two states: one permit available or zero permits available.
为此,它只保留一个可供访问的许可。因此,一个二进制信号灯只有两种状态:一个可用的许可或零个可用的许可。
Let’s discuss a simple implementation of a binary semaphore using the Semaphore class available in Java:
让我们讨论一个简单的二进制信号灯的实现,使用Java中可用的Semaphore类。
Semaphore binarySemaphore = new Semaphore(1);
try {
binarySemaphore.acquire();
assertEquals(0, binarySemaphore.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
binarySemaphore.release();
assertEquals(1, binarySemaphore.availablePermits());
}
Here, we can observe that the acquire method decreases the available permits by one. Similarly, the release method increases the available permits by one.
在这里,我们可以看到,acquire方法使可用的许可证减少了一个。同样地,release方法使可用的许可证增加一个。
Additionally, the Semaphore class provides the fairness parameter. When set to true, the fairness parameter ensures the order in which the requesting threads acquire permits (based on their waiting time):
此外,Semaphore类提供了fairness参数。当设置为true时,fairness参数确保请求线程获得许可的顺序(基于它们的等待时间)。
Semaphore binarySemaphore = new Semaphore(1, true);
3. What Is a Reentrant Lock?
3.什么是可重入锁?
A reentrant lock is a mutual exclusion mechanism that allows threads to reenter into a lock on a resource (multiple times) without a deadlock situation.
再入锁是一种互斥机制,允许线程在不出现死锁情况下重新进入一个资源的锁(多次)。
A thread entering into the lock increases the hold count by one every time. Similarly, the hold count decreases when unlock is requested. Therefore, a resource is locked until the counter returns to zero.
一个进入锁的线程每次都会增加一个保持数。同样地,当请求解锁时,保持计数也会减少。因此,一个资源被锁定,直到计数器返回到0。
For instance, let’s look at a simple implementation using the ReentrantLock class available in Java:
例如,让我们看看使用Java中可用的ReentrantLock类的一个简单实现。
ReentrantLock reentrantLock = new ReentrantLock();
try {
reentrantLock.lock();
assertEquals(1, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());
} finally {
reentrantLock.unlock();
assertEquals(0, reentrantLock.getHoldCount());
assertEquals(false, reentrantLock.isLocked());
}
Here, the lock method increases the hold count by one and locks the resource. Similarly, the unlock method decreases the hold count and unlocks a resource if the hold count is zero.
这里,lock方法将保持数增加1并锁定了资源。同样地,unlock方法减少保持数,并在保持数为零时解锁资源。
When a thread reenters the lock, it has to request for the unlock the same number of times to release the resource:
当一个线程重新进入该锁时,它必须请求解锁的次数相同,以释放资源。
reentrantLock.lock();
reentrantLock.lock();
assertEquals(2, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());
reentrantLock.unlock();
assertEquals(1, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());
reentrantLock.unlock();
assertEquals(0, reentrantLock.getHoldCount());
assertEquals(false, reentrantLock.isLocked());
Similar to the Semaphore class, the ReentrantLock class also supports the fairness parameter:
与Semaphore类类似,ReentrantLock类也支持fairness参数。
ReentrantLock reentrantLock = new ReentrantLock(true);
4. Binary Semaphore vs. Reentrant Lock
4.二进制占位符与可重入锁的比较
4.1. Mechanism
4.1 机制
A binary semaphore is a type of signaling mechanism, whereas a reentrant lock is a locking mechanism.
二进制信号灯是一种信号机制,而可重入锁是一种锁定机制。
4.2. Ownership
4.2.所有权
No thread is the owner of a binary semaphore. However, the last thread that successfully locked a resource is the owner of a reentrant lock.
没有线程是二进制信号的所有者。然而,最后一个成功锁定资源的线程是一个可重入锁的所有者。
4.3. Nature
4.3 自然
Binary semaphores are non-reentrant by nature, implying that the same thread can’t re-acquire a critical section, else it will lead to a deadlock situation.
二进制信号系统在本质上是不可逆的,这意味着同一个线程不能重新获得一个关键部分,否则会导致死锁的情况。
On the other side, a reentrant lock, by nature, allows reentering a lock by the same thread multiple times.
另一方面,从本质上讲,可重入锁允许同一线程多次重入一个锁。
4.4. Flexibility
4.4.灵活性
A binary semaphore provides a higher-level synchronization mechanism by allowing a custom implementation of a locking mechanism and deadlock recovery. Thus, it gives more control to the developers.
二进制信号灯提供了一种更高级的同步机制,它允许自定义实现锁定机制和死锁恢复。因此,它给了开发者更多的控制权。
However, the reentrant lock is a low-level synchronization with a fixed locking mechanism.
然而,可重入锁是一种具有固定锁机制的低级同步。
4.5. Modification
4.5.修改
Binary semaphores support operations like wait and signal (acquire and release in the case of Java’s Semaphore class) to allow modification of the available permits by any process.
二进制信号支持像等待和信号(在Java的Semaphore类中为获取和释放)这样的操作,以允许任何进程修改可用的许可。
On the other hand, only the same thread that locked/unlocked a resource can modify a reentrant lock.
另一方面,只有锁定/解锁资源的同一线程才能修改可重入锁。
4.6. Deadlock Recovery
4.6.死锁恢复
Binary semaphores provide a non-ownership release mechanism. Therefore, any thread can release the permit for a deadlock recovery of a binary semaphore.
二进制semaphores提供了一种非所有权的释放机制。因此,任何线程都可以为二进制信号的死锁恢复释放许可。
On the contrary, deadlock recovery is difficult to achieve in the case of a reentrant lock. For instance, if the owner thread of a reentrant lock goes into sleep or infinite wait, it won’t be possible to release the resource, and a deadlock situation will result.
相反,在可重入锁的情况下,死锁恢复很难实现。例如,如果可重入锁的所有者线程进入睡眠或无限等待状态,就不可能释放资源,从而导致死锁情况。
5. Conclusion
5.总结
In this short article, we’ve explored binary semaphore and reentrant locks.
在这篇短文中,我们已经探讨了二进制信号和可重入锁的问题。
First, we discussed the basic definition of a binary semaphore and a reentrant lock, along with a basic implementation in Java. Then, we compared them against each other based on a few parameters like mechanism, ownership, and flexibility.
首先,我们讨论了二进制信号和可重入锁的基本定义,以及Java中的基本实现。然后,我们根据一些参数,如机制、所有权和灵活性,对它们进行了相互比较。
We can certainly conclude that a binary semaphore provides a non-ownership-based signaling mechanism for mutual exclusion. At the same time, it can be further extended to provide locking capabilities with easy deadlock recovery.
我们当然可以得出结论:二进制信号灯为相互排斥提供了一种非所有权的信号机制。同时,它还可以进一步扩展,以提供易于恢复死锁的锁定功能。
On the other hand, a reentrant lock provides a reentrant mutual exclusion with owner-based locking capabilities and is useful as a simple mutex.
另一方面,可重入锁提供了一个可重入的互斥,具有基于所有者的锁定功能,并且作为一个简单的mutex很有用。
As usual, the source code is available over on GitHub.
像往常一样,源代码可在GitHub上获得。