Apache Curator Lock Рецепты отмены
Я пытаюсь протестировать отзывную блокировку в Apache Curator. У меня есть два потока, которые пытаются получить блокировку. Если первый тест получает блокировку, второй поток может попросить первый поток снять блокировку, чтобы 2-й поток мог ее получить
RetryPolicy retryPolicy = new ExponentialBackoffRetry(baseSleepTimeMills, maxRetries);
CuratorFramework client = CuratorFrameworkFactory.newClient(hosts, retryPolicy);
client.start();
final InterProcessMutex lock = new InterProcessMutex(client, lockBasePath);
Collection<String> nodes = lock.getParticipantNodes();
lock.makeRevocable(new RevocationListener<InterProcessMutex>(){
@Override
public void revocationRequested(InterProcessMutex lock1) {
try {
if(lock.isAcquiredInThisProcess()){
lock.release();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
if(nodes!=null && !nodes.isEmpty()){
Revoker.attemptRevoke(client, nodes.iterator().next());
}
if (lock.acquire(waitTimeSeconds, TimeUnit.SECONDS)) {
try {
doSomeWork(lockName);
} finally {
lock.release();
}
} else {
System.err.printf("%s timed out after %d seconds waiting to acquire lock on %s\n",
lockName, waitTimeSeconds, lockPath);
}
Проблема заключается в том, что когда 2-й поток вызывает попытку Revoke, асинхронный метод обратного вызова вызывается в первом процессе, но, поскольку его метод обратного вызова является третьим потоком, и, если он вызывает блокировку.
java.lang.IllegalMonitorStateException: у вас нет блокировки
Это согласно API
release() Выполните одно освобождение мьютекса, если вызывающий поток является тем же потоком, который его получил.
Так что в принципе это никогда не возможно, потому что обратные вызовы всегда будут другим потоком. Есть ли другой способ добиться этого?
Спасибо за любые предложения
-Tatha
2 ответа
Ты можешь использовать InterProcessSemaphoreMutex
вместо InterProcessMutex
снять блокировку в другом потоке.
ref: Возможность освободить InterProcessMutex из другого потока #117
Ваш RevocationListener должен прервать поток, который удерживает блокировку. Затем этот поток может снять блокировку.