2

I am trying to test the revocable Locking in Apache Curator. I have two threads which tries to acquire a lock. If the first test acquires the lock, the second thread can ask the first thread to release the lock so that the 2nd thread can acquire it

        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);
        }

The problem is, when the 2nd thread calls the attemptRevoke, the callback async method is called on the first process, but since its a call back method that's a third thread, and if that invokes the lock.release it throws an Exception

java.lang.IllegalMonitorStateException: You do not own the lock

That is as per the api

release() Perform one release of the mutex if the calling thread is the same thread that acquired it.

So basically this is never possible because callbacks will always be another thread. Is there any other way to achieve this?

Thanks for any suggestions

-Tatha

Tatha
  • 1,253
  • 2
  • 24
  • 42
  • @Randgalt mentioned about revocation recipes in http://stackoverflow.com/questions/27113914/apache-zookeeper-curator-time-to-live-on-locks?rq=1 – Tatha Oct 27 '15 at 19:13

2 Answers2

2

You can use InterProcessSemaphoreMutex instead of InterProcessMutex to release the lock in another thread.

ref: Ability to release an InterProcessMutex from another thread #117

Wuaner
  • 929
  • 2
  • 14
  • 31
1

Your RevocationListener should interrupt the thread that holds the lock. Then, that thread can release the lock.

Randgalt
  • 2,907
  • 1
  • 17
  • 31
  • Can you provide an example? I don't see how the InterProcessMutex can do: 1.) call `acquire()` 2.) execute code 3.) avoid calling `release()` and be able to revoke the lock that was previously acquired. Making the mutex revocable implies that the thread that calls `acquire()` must block and wait to be interrupted. – Man Vs Code Jan 07 '21 at 18:12