• Post Reply Bookmark Topic Watch Topic
  • New Topic

Reentrant locks - Unlocking from another thread

 
Paul Hilliar
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all

I am extending a processing engine to be cluster aware. There is a lock manager component that sits only on the master node.

This lock manager currently uses the Java 5 reentrant lock, and on a single node this works very nicely.

The problem is that when a slave node goes down, I want to be able to release all the locks that were held by that node.

Not a problem to find those locks but there is a problem releasing them. A restriction exists in ReentrantLock.Sync.tryRelease to enforce a restriction that the lock can only be released by the thread that acquired it

This restriction is really annoying. Can anyone suggest a workaround or a different reentrant locking implementation that doesn't have this restriction.

I could allocate one thread on the master for each slave node and make that do the work on behalf of the slave node but that is a real last resort.


Any help would be much appreciated - thanks in advance


Paul.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You might think about using a Semaphore with one permission as a locking mechanism. The Semaphore allows different threads to add permissions to the Semaphore, effectively un-locking it.

You could probably write a Lock implementation based on the single permission Semaphore. Another option would be to write a Lock implementation that uses the LockSupport class. I am not exactly sure how it works but I think it follows the same principle as the Semaphore.
 
Henry Wong
author
Sheriff
Posts: 22536
109
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I find it very difficult to believe that unlocking a lock that belongs to another thread is actually an option here. Think about it. This other thread that died could have left, whatever that was being protected, in an interium state.

For absolute safety, I am assuming that some cleanup needs to happen before this lock is going to be "freed". And if that is going to happen, maybe it would be better to create a new lock, interrupt everyone on the old lock, so that they know that a cleanup occurred, and can reinitialize onto the new lock.

Henry

 
Paul Hilliar
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No I definitely do want to release the lock. XA is protecting me and the point of what I am doing is detecting and clearing up resources.

Semephore is a great idea but I am concerned that the solution will effectively cause a memory leak due to the following scenario:

Thread on a slave node requests a lock
This request is served over Spring RMI remoting to the lock manager
Lock Manager allocates a lock and the RMI call returns
At the end of the transaction on the slave, it calls up the lock manager again over RMI and releases the lock.

The problem is that the thread that services the RMI call is just a random one from the thread pool. We would therefore end up with an ever-increasing list of semephores.


My current solution is that I have taken the code from ReentrantLock and modified it so that instead of every check on Thread.currentThread, I do a check on a ThreadLocal id that I have set on the current thread, tying it to the thread in the remote VM. (Have tried to attach this but Javaranch isn't playing ball!)

It is a pretty hacky solution though - any better ideas?
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Hilliar wrote:
The problem is that the thread that services the RMI call is just a random one from the thread pool. We would therefore end up with an ever-increasing list of semephores.


I am not sure about this. I guess what steve is saying that you can replace your existing lock with a semaphore with one permit. This allows you to add/release permits from any thread which is equivalent to locking/unlocking a lock. So, whatever applies to the lock also applies to the semaphore i.e. if the locks were not an ever-increasing list then semaphore also will not be.
Sorry if i missed something here.
 
Paul Hilliar
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK I have looking into it further and you are right - Semaphore would be a good solution It won't memory leak because there is no permission object, just a counter

Locks can be acquired and released from different threads, which works a treat. Ideally I would like to restrict the Semaphore from growing its permit pool past one. Then I would be protected to some extent from dodgy coding. Any ideas on this?

Thanks for the help everyone.
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is from the javadocs:

A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock.


This constructor creates a semaphore with the desired number of *maximum* permits, which in your case is 1.
 
Paul Hilliar
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
...so it can't 100% enforce a max number of permits then. That's a shame.

I would have thought that a useful enhancement would be to throw PermitLimitExceededException or similar when you try to release so the available permits would be greater than the max permits.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!