Reputation: 1389
I'm trying to assert whether or not, using LockSupport.park(Object blocker)
realeases the monitor lock object of blocker. That is : if called in a section synchronized on blocker
, will the monitor lock of blocker
be released ?
Here's a junit test I made that make me think it's the case.
I know a Thread is in state WAITING
as a consequence of calling Òbject.waitor LockSupport.park()
which looks to me like the same underlying mechanism is used. However, the javadoc doesn't explicitly clarifies my question, so i'm not sure.
final Object blocker = new Object();
final Thread thread = new Thread() {
@Override
public void run() {
synchronized(blocker) {
while(!interrupted()) {
assertTrue(holdsLock(blocker));
LockSupport.park(blocker);
}
}
}
};
try {
thread.start();
while(thread.getState() != Thread.State.WAITING)
Thread.sleep(100);
assertEquals(0, ManagementFactory.getThreadMXBean().getThreadInfo(thread.getId()).getLockedMonitors().length);
} finally {
thread.interrupt();
}
Upvotes: 2
Views: 738
Reputation: 120998
First of all your code is flawed, by simply using the:
ManagementFactory.getThreadMXBean().getThreadInfo(thread.getId())
as it says in the documentation (it says this method is equivalent to calling getThreadInfo(id, 0)
and the latter one says )
... does not obtain the locked monitors and locked synchronizers of the threads
so that array is always going to be zero length.
So if you want proof code wise:
public class DeleteMe3 {
public static void main(String[] args) {
Object lock = new Object();
System.out.println(lock.toString());
Thread thread = new Thread() {
@Override
public void run() {
synchronized (lock) {
boolean holdLock = Thread.holdsLock(lock);
if (!holdLock) {
throw new AssertionError("Does not hold lock");
} else {
System.out.println("I hold the lock");
}
System.out.println("Before parking");
LockSupport.park(lock);
}
}
};
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
showIfAnyLocksHeld(thread.getId());
System.out.println("Unparking... ");
LockSupport.unpark(thread);
}
private static void showIfAnyLocksHeld(long threadId) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.getThreadInfo(new long[] { threadId }, true, true);
if (infos.length == 0) {
System.out.println("Thread we are interested in has died");
return;
}
MonitorInfo[] mInfos = infos[0].getLockedMonitors();
if (mInfos.length == 0) {
System.out.println("No locks held by thread " + threadId);
return;
}
System.out.println("Thread with id = " + threadId + " holds lock(s) : " +
Arrays.stream(mInfos).map(MonitorInfo::toString).collect(Collectors.joining(" ; ")));
}
}
Output is going to contain:
java.lang.Object@5f2108b5
I hold the lock
Before parking
Thread with id = 12 holds lock(s) : java.lang.Object@5f2108b5
So you can tell that LockSupport.park
will not release the lock; but it would be otherwise weird if it did; unless it would be documented as such, which it does not.
Upvotes: 1
Reputation: 1904
The simple answer is no. LockSupport is not meant for general application programming. Since there is no protection (as provided for with synchronized wait/notify) you need explicit control over the entire threading environment. That is, you cannot use third party software and expect it to conform to your standards.
For a good example of how to use park/unpark look at the source for ForkJoinPool.
Upvotes: 2
Reputation: 1575
If the javadoc doesn't define the behavior, it is undefined ;)
Don't depend on it for anything.
Upvotes: 1