JDK-8230240 : AQS and lock classes refresh
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Priority: P2
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 14
  • Submitted: 2019-08-27
  • Updated: 2019-09-04
  • Resolved: 2019-08-31
Related Reports
CSR :  
Description
Summary
-------
Method `LockSupport.setCurrentBlocker` was added as part of JDK-8229442 mainly to allow implementations to maintain compatibility with tools and
utilities reporting `LockSupport.getBlocker` when threads are parked.

Problem
-------
The primary rationale for this method is to allow people to improve
compatibility with previous implementations that includes calls to `LockSupport.park`,  with respect to tools expecting a particular type of blocker object to be reported in stack traces etc. 

Solution
--------

`LockSupport.setCurrentBlocker` allows a given blocker to be set instead of per-park arguments for upcoming calls to park that may be performed in some other object.


Specification
-------------
    /**
     * Sets the object to be returned by invocations of {@link
     * #getBlocker getBlocker} for the current thread. This method may
     * be used before invoking the no-argument version of {@link
     * LockSupport#park() park()} from non-public objects, allowing
     * more helpful diagnostics, or retaining compatibility with
     * previous implementations of blocking methods.  Previous values
     * of the blocker are not automatically restored after blocking.
     * To obtain the effects of {@code park(b}}, use {@code
     * setCurrentBlocker(b); park(); setCurrentBlocker(null);}
     *
     * @param blocker the blocker object
     * @since 14
     */
    public static void setCurrentBlocker(Object blocker) {
        U.putObjectOpaque(Thread.currentThread(), PARKBLOCKER, blocker);
    }


Comments
Moving to Approved.
31-08-2019

Sure. Done.
29-08-2019

The stacking issue is the same as what Martin asked: > If you call setBlocker(x) followed by park(y), y wins. Should that be specified? I think this needs to be made more clear. Thanks.
29-08-2019

I don't think it needs mention in the class-level docs. The method is mainly there for the very few people looking for something that allows them to change a blocking method implementation without changing reporting by tools. These people will find it. We would have left this as internal except that I have heard from people that they could not change methods to use FJP.ManagedBlocker or make other internal changes because of these tool-compatibility issues. I don't think there will ever be more than a few handfuls of users though. The method does not claim to "stack" before-after usages, although it would be possible for someone to do this now given the existence of this method plus getBlocker.Conceivably useful.
29-08-2019

Minor edits made. Doug: do you want to also add something to the blocker paragraph in the LockSupport class docs to mention the new method? I'm a little unclear on the expected usage here. Is this for end-user use or library developer use or both? It seems to require breaking encapsulation and could be redundant if a library gets updated to add the blocker itself. If you use this around calls that already set the blocker then it may not work as expected e.g.: setBlocker(f); f.someParkingMethod(); // calls park(this); assert getBlocker() == f; // FAILS: getBlocker() -> NULL
29-08-2019

LGTM
29-08-2019

Thanks Martin. I clarified accordingly (as updated above).
28-08-2019

Doug, please have Martin or other 166-alpha sort of person review the API change before it is re-finalized. For now, until it has a reviewer, I'm moving the CSR to the intermediate Provisional state.
28-08-2019

So this is used when calling into an API that calls one of the park methods, that does not take a blocker object, internally? In which case it might be better to say that explicitly. If you link to one of the park methods, explicitly link to #park() not #park, since the latter might link to park(Object blocker). If you call setBlocker(x) followed by park(y), y wins. Should that be specified?
28-08-2019