RFR: 8351565: Implement JEP 502: Stable Values (Preview)
John Rose
john.r.rose at oracle.com
Sun Mar 16 03:19:38 UTC 2025
On 13 Mar 2025, at 4:20, Per Minborg wrote:
> …
>> Reentrancy into here seems really buggy, I would endorse disallowing it >> instead. In that case, a `ReentrantLock` seems better than the native monitor as we can cheaply check `lock.isHeldByCurrentThread()`
>
> StableValueImpl was carefully designed to minimize memory footprint. Adding a lock would inflate memory usage substantially.
+1 from me
A similar level of concern with footprint was in my mind in my
earlier comment, where I claimed that capturing /this/ in a lambda
is suboptimal. The inefficiency is in object creation and footprint,
since an extra copy of /this/ must be tracked.
>
>> src/java.base/share/classes/jdk/internal/lang/stable/StableValueImpl.java line 159:
>>
>>> 157: private boolean wrapAndCas(Object value) {
>>> 158: // This upholds the invariant, a `@Stable` field is written to at most once
>>> 159: return UNSAFE.compareAndSetReference(this, UNDERLYING_DATA_OFFSET, null, wrap(value));
>>
>> There is no need for a cas here as all setters have to hold the lock. We should have a dedicated private `set` that asserts `Thread.holdsLock(this)`.
>
> This is more of a belt and suspenders solution. It is true that it is redundant. A set volatile would suffice here.
There is a broad choice at the beginning of this design whether
to use a mutex (as <clinit> and ClassValue do) or use lock-free
CAS (as condy/indy do). This API, which is more parallel to
the higher-level <clinit> and ClassValue, uses a mutex.
The choice connects to the rules about handling races. Surely,
two threads can ask concurrently for a SV state, and both may
“suggest” a lambda to give it a value. Now we come to a fork
in the road: Do we select at most one lambda to run? Or,
do we let both lambdas run and then pick a winner? The first
requires a mutex. The second is lock-free and uses CAS.
It’s a binary choice. I don’t think we ever need the belt
and suspenders. I agree that StableValue is like ClassValue
and not like condy, so it should not be playing with lock
free stuff. (Or did I forget something??)
— John
More information about the core-libs-dev
mailing list