JDK 9 RFR of JDK-8035279: Clean up internal deprecations in BigInteger
Stuart Marks
stuart.marks at oracle.com
Thu Feb 20 20:04:05 UTC 2014
On 2/20/14 9:55 AM, Peter Levart wrote:
> On 02/20/2014 11:20 AM, David Holmes wrote:
>> re: volatile
>>
>> The basic approach being taken with these primitive fields is lazy
>> initialization to a value that will always be the same if recomputed. If the
>> variables are not volatile then in the worst-case (this is theoretical only)
>> they will be recomputed by each thread that accesses them. If they are
>> volatile then they will only be recomputed by threads that truly race on the
>> initialization logic, but you will thereafter pay the price of a volatile read
>> on each access.
>>
>> Either way you will be functionally correct so it all comes down to
>> performance. Practically speaking I would expect you to be better off overall
>> without the volatile.
>
> I would also be concerned about correctness here. You changed fields to be
> volatile and assigned them with different that default (zero) values in field
> initializers. Take for example the field bitCount:
>
> | 156 private volatile int bitCount = Integer.MIN_VALUE;|
>
> In code you check this initial value and decide whether to lazily compute the
> real value or not based on this check:
>
> 3298 public int bitCount() {
> 3299 // This computation has a known, acceptable non-critical race
> condition.
> 3300 if (bitCount == Integer.MIN_VALUE) { // bitCount not initialized yet
>
> There has recently been a discussion on concurrency-dev mailing list about
> whether this is safe:
>
> http://cs.oswego.edu/pipermail/concurrency-interest/2013-November/011951.html
>
> ...in cases where the instance of such constructed object escapes to
> non-constructing thread via data-race. I think the conclusion was that such
> semantics is desirable and might be guaranteed in a future updated JMM, but
> currently it is not, although most JVMs are implemented in such a way that this
> is safe.
Arrrgh. Yet another hairy JMM discussion .... :-)
Brian and I had a discussion about this internally, and I recommended volatile,
but mainly because I couldn't convince myself that it was correct in the absence
of volatile. But my understanding of the JMM could be wrong (I think I'm in good
company here) so I appreciate the additional discussion.
In the context of the November concurrency-interest discussion, the phrase
"escape ... via data race" implies to me that the object is *not* safely
published. My assumption is that if the BigInteger is safely published, there is
no issue. If it's not safely published, then other threads could see the default
value (zero) of bitCount instead of the sentinel value MIN_VALUE, rely on zero
improperly, and end up computing an incorrect result. That would be bad.
Making the field volatile would mitigate this issue, or so I thought.
> Citing Doug Lea:
>
> "
> Right. To summarize:
>
> * Programmers do not expect that even though final fields are specifically
> publication-safe, volatile fields are not always so.
Yes -- this is a surprise to me.
Two more data points:
- String.hash is not volatile but is potentially written by any thread. This
is a similar data race. But it's not initialized at construction time, and the
code uses the default value zero as a special case.
- Joe Darcy updated the bug report with a pointer to some discussion that
occurred several years ago on core-libs-dev, which was the code review of the
changes that introduced the code Brian is proposing to change. I'll include the
link here for convenience:
http://mail.openjdk.java.net/pipermail/core-libs-dev/2009-February/001105.html
(I haven't read it yet.) It may shed some light on the current discussion.
> Is there a special reason you changed the "uninitialized" value from default
> (zero) to non-zero?
Zero is a valid value for some (all?) of the fields, so zero can't be used
directly as an "uninitialized" sentinel. The previous code offset the value
space to allow zero as a sentinel, at a cost of sprinkling +1's, -1's, +2's, and
-2's throughout the code.
s'marks
More information about the core-libs-dev
mailing list