Antoine Marques
Antoine Marques

Reputation: 1389

Does LockSupport.park(Object) releases monitor lock of blocker object

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 blockerbe 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

Answers (3)

Eugene
Eugene

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

edharned
edharned

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

Norwæ
Norwæ

Reputation: 1575

If the javadoc doesn't define the behavior, it is undefined ;)

Don't depend on it for anything.

Upvotes: 1

Related Questions