Solved

Being able to pass a lock between threads?

Posted on 2014-11-19
4
238 Views
Last Modified: 2014-11-24
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?
0
Comment
Question by:Javin007
4 Comments
 
LVL 26

Accepted Solution

by:
dpearson earned 500 total points
ID: 40453129
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
 
LVL 16

Expert Comment

by:krakatoa
ID: 40453266
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
 
LVL 35

Expert Comment

by:mccarl
ID: 40453998
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
 
LVL 4

Author Closing Comment

by:Javin007
ID: 40462489
Looks like semaphores are the direction I needed to go in. Thanks!
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
The viewer will learn how to implement Singleton Design Pattern in Java.

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now