Apache zookeeper 策展人进程间互斥与进程间信号量互斥

Apache zookeeper 策展人进程间互斥与进程间信号量互斥,apache-zookeeper,apache-curator,Apache Zookeeper,Apache Curator,进程间互斥与进程间信号量互斥之间有什么区别?say进程间信号量互斥与进程间互斥相同,只是它不是可重入的。但我不知道可重入性是什么意思。在此上下文中,可重入性意味着线程可以多次调用同一个锁上的acquire,并且在第二次或第三次调用时不会阻塞它。然而,它必须用相同数量的发布来平衡所有的收购。这篇StackOverflow文章详细介绍了重入锁: 针对策展人,以下是文档中关于不同锁的说明: : public void acquire() 获取互斥锁阻塞,直到 可用。注意:同一线程可以重新调用acqu

进程间互斥
进程间信号量互斥
之间有什么区别?say
进程间信号量互斥
进程间互斥
相同,只是它不是可重入的。但我不知道可重入性是什么意思。

在此上下文中,可重入性意味着线程可以多次调用同一个锁上的acquire,并且在第二次或第三次调用时不会阻塞它。然而,它必须用相同数量的发布来平衡所有的收购。这篇StackOverflow文章详细介绍了重入锁:

针对策展人,以下是文档中关于不同锁的说明:

:

public void acquire()

获取互斥锁阻塞,直到 可用。注意:同一线程可以重新调用acquire。每个 必须通过调用release()来平衡对acquire的调用

:

public void acquire()

获取互斥锁阻塞,直到它可用。必须通过调用release()来平衡

在下面的示例中,如果
lock
是一个可重入的锁,那么下面的代码将运行到完成并正常工作。如果
lock
不是可重入锁,则线程将在调用第二个
lock.acquire()时死锁:

可重入锁的实现成本往往稍高一些,但更易于使用

当您的API中有多个必须锁定的公共方法,但您的实现有调用其他公共方法的公共方法时,上述模式经常发生。您可以通过让您的公共方法执行锁定和仅锁定来避免这种情况,然后调用一个私有方法,该方法假定它总是在锁下执行;然后,您的私有方法可以调用其他私有方法,而无需多次获取锁

编辑以解决@Randgalt的评论:

Curator的进程间互斥要求获取锁的线程释放它。进程间信号量EMUTEX不支持。也许你误读了我写的东西?也许我不清楚?不知道。无论如何,情况就是这样

这显然是错误的;这两个锁都不允许从获取锁的线程以外的线程释放它。此外,在这种情况下,这与“什么是重入性”的问题毫无关系——在这种情况下,重入性是指是否可以在同一线程上多次调用同一锁上的acquire

:

public void release()

如果调用线程与获取互斥锁的线程相同,则执行互斥锁的一次释放。如果线程多次调用acquire,则当此方法返回时,互斥锁仍将保持

:

public void release()

如果调用线程与获取互斥锁的线程相同,则执行互斥锁的一次释放。


重点补充。这两个锁都不允许从拥有锁的线程之外的任何线程解锁它,这是有意义的,因为两个锁都是互斥锁,这是互斥锁的属性之一。

我是Apache Curator的主要作者。不管文档可能会说什么,也可能不会说什么,为了记录在案,我想给出这两个类中每个类的确切用例

进程间互斥

当您需要能够以重入方式锁定时,应使用进程间互斥。这意味着一个给定的线程在获得锁后被称为“拥有”锁,如果需要可以再次锁定它。如果线程将lock对象传递给其他方法,而这些方法不需要考虑是否已获取锁,那么这将非常有用。请注意,这也意味着只有拥有线程才能释放锁。下面是一个例子:

InterProcessMutex lock = new InterProcessMutex(...);

if ( !lock.acquire(...) ) ... // if acquire failed: throw, return, etc
try {
   doWork(lock);    // doWork() can safely call lock.acquire() again on the lock
} finally {
    lock.release();
}
一旦获取,如果在与用于获取锁的线程不同的线程中释放锁,则会抛出
IllegalMonitorStateException

进程间信号量emutex

进程间SemaphoreUnitex
是锁的放松版本,它不记录获取它的线程。它具有更简单的语义。每个进程间SemaphoreMutex实例可以只获取一次,并且必须通过发布(在任何线程中)进行平衡。i、 e


我希望这有帮助。如果文档需要澄清,我们将非常感谢您的改进请求。

感谢您的回复。非重入锁似乎更容易出现死锁。是否有一个使用非重入优于重入锁的用例?很多时候,您无法从获取锁的同一线程中释放锁(或者您不在乎)。在这些情况下,非重入锁是选择。@Randgalt-这不准确。在此上下文中,可重入性是关于获取锁,而不是释放锁。大多数互斥实现明确禁止您的确切用例;如果所属线程以外的任何线程试图释放锁,它们将报告某种错误,因为这是互斥锁的目的——在该线程释放锁之前,互斥锁仅由一个线程拥有。您的用例将由信号灯或类似的东西提供服务。如您所述,任何使用互斥锁的尝试都是错误的,无论它是否正常工作。@antiduh Curator的进程间互斥锁要求获取锁的同一线程释放它。进程间信号量EMUTEX不支持。也许你误读了我写的东西?也许我不清楚?不知道。无论如何,情况就是这样。@Randgalt-请看我的编辑;你还是完全错了。Reentrancy不仅与释放无关,而且您关于“InterProcessSemaphoreMutex不[需要从获取它的同一线程释放]”的断言是完全错误的。而且您对“Reentrancy”的定义与社区接受的定义不同。参考文献
InterProcessMutex lock = new InterProcessMutex(...);

if ( !lock.acquire(...) ) ... // if acquire failed: throw, return, etc
try {
   doWork(lock);    // doWork() can safely call lock.acquire() again on the lock
} finally {
    lock.release();
}
InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(...);

lock.acquire();
lock.acquire();    // this will block forever