Being able to pass a lock between threads?

MCCarl:  This one's for you!  

You suggested the "reentrant lock" in another thread, and I've been looking at it, and it looks like it MIGHT be just what I need.  Here was the code I'd written:  

//Theoretically, this should allow objects to be synchronized across methods and threads instead of just within a single method.
//In practice, this will probably just cause a ton of race conditions and problems.
public class Synchronizer {

	//Track the synchronization of the object manually.
	boolean booLocked = false;
	
	//This is my attempt at a public locking mechanism that will (theoretically) allow thread safety across methods.
	//So if they want to turn the lock "on" first, do the system sync.
	public synchronized void lock() {

		//Now, if the thread is this far, but the boolean shows that the sync is already "on" have the thread wait until it's available.
		while (booLocked) {
			//Allow other threads to run if needed.
			Thread.yield();
		}
		//Theoretically, if we're this far, only one thread should have been permitted to get through the system's "synchronized" function.  So flipping the "locked"
		//to "true" then stepping out of the sync should allow any competing threads to get through one at a time and wait for the boolean to be flipped to "false" again.
		booLocked = true;
 
	}
	
	public void unLock() {
		//Simply flip the switch to unlock.
		booLocked = false;
	}
	
}

Open in new window


The idea would be for me to be able to have an object that can be passed between threads, so that a "lock" on an object would no longer be limited to the method that "synchronized" was called in.  I wrote this code to give me an object that I could pass around like a baton, and only after the CORRECT object called "unlock" could anything be done.  This object that unlocks it, though, might not be in the same thread as the one that locked it.  

Basically, imagine a scenario where I have one thread whose job is to "load and lock" objects, then toss them into a queue.  Other threads will be trying to get at these objects, but will have to wait until they're unlocked.

Another thread picks up any objects in this queue, does some stuff to them, then "unlocks" them, allowing the other threads access to grab and lock them themselves.  

One lock object, used by all threads, but the lock and unlock does not necessarily have to happen within the same thread.  That's the goal behind this code.  

Is this what the ReentrantLock does?  

According to the Oracle docs:  

It is recommended practice to always immediately follow a call to lock with a try block, most typically in a before/after construction such as:

 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

Open in new window


This seems to indicate that once again, within the same method, the locks and unlocks should be together.  Am I reading this wrong?
LVL 4
Javin007Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

dpearsonCommented:
If the goal is to have Thread A lock an object and Thread B unlock it, then I don't think you can use ReentrantLock because only the locking thread can unlock it:

public void unlock()
Attempts to release this lock.
If the current thread is the holder of this lock then the hold count is decremented. If the hold count is now zero then the lock is released. If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown.

I think instead you maybe want to use a Semaphore
(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html)

A Semaphore conceptually is more of a set of flags - which you can then use to decide when somebody can do an operation or not.  (You can use a Semaphore to implement the concept of a Lock - they're more primitive than a Lock).  The big difference for you is the "release()" method for a Semaphore is not thread specific:

public void release()
Releases a permit, returning it to the semaphore.
Releases a permit, increasing the number of available permits by one. If any threads are trying to acquire a permit, then one is selected and given the permit that was just released. That thread is (re)enabled for thread scheduling purposes.

There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.

Doug
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
krakatoaCommented:
My name's not mccarl either, but as mentioned before, util.concurrent holds many useful classes, and CyclicBarrier is one you can also read up on.

And "passing a lock" is not only going to be clock-costly, but is not really in the paradigm. Using a thread-superior mechanism that is already in the model is preferable.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
As Doug has said, it sounds like Semaphore is what you may need, however, I am interested more in your core requirements. You said...

Basically, imagine a scenario where I have one thread whose job is to "load and lock" objects, then toss them into a queue.  Other threads will be trying to get at these objects, but will have to wait until they're unlocked.

Another thread picks up any objects in this queue, does some stuff to them, then "unlocks" them, allowing the other threads access to grab and lock them themselves.  
Now, you may have simplified this a bit just to describe it here, but if this were the actual requirement, could you implement by using 2 queues. The first thread you mention above would load objects onto one queue. Then the last thread that you mention can "...picks up any objects in this queue, does some stuff to them..." BUT then it places them on a 2nd queue. Then these "other threads" can get the objects from the 2nd queue. There is no locking required at all now.

As I said, I'm guessing the actual requirements are more than just this and that may have an impact, so if you can more fully describe what you need, we may be able to provide more assistance.
0
Javin007Author Commented:
Looks like semaphores are the direction I needed to go in. Thanks!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.