Why not lock on a value-based class
Here's what a Blog post by Nicolai Parlog says about value-based classes:
In Java 8 value types are preceded by value-based classes. Their precise relation in the future is unclear but it could be similar to that of boxed and unboxed primitives (e.g. Integer and int). Additionally, the compiler will likely be free to silently switch between the two to improve performance. Exactly that switching back and forth, i.e. removing and later recreating a reference, also forbids identity-based mechanisms to be applied to value-based classes.
So what Nicolai is saying is this:
In the future, compilers may do things that transparently translate between values and value-based classes in ways that do not preserve object identity.
Certain things ("identity-based mechanisms") depend on object identity. Examples include the semantics of
==
for references, identity hashcode, primitive locking, and object serialization.For those things, there is the potential that the transparent translation won't be transparent.
In the case of primitive locking, the concern is that something like the following sequence may occur.
- An instance of a value-based class is created.
- The instance is converted to a value behind the scenes.
- The value is then converted back, giving a different object.
If two threads then use "the instance" as a primitive lock, they could be unaware that in fact there are in fact two objects (now). If they then attempted to synchronize
, they would (could) be locking different objects. That would mean there was no mutual exclusion on whatever the state was that the locking was intended to protect.
If you don't lock on a value-based class, you won't have to worry about that potential hazard ... in the future.
But note, that Nicolai's blog posting is one person's speculation on what might happen in Java 10 or later.
BTW, I understand the reasons not to lock on Integers and other primitive-wrapper classes; they may be cached.
Caching is not the problem per se, but a mechanism that gives rise to the problem. The real problem is that it is difficult to reason about the object identity of the lock object, and hence whether the locking regime is sound.
With the the primitive wrappers, it is the semantics of boxing and unboxing that gives rise uncertainty of object identity. Going forward, the mooted value type <-> object conversion would be another source of this uncertainty.
The above blog is based on "State of the Values" April 2014. John Rose, Brian Goetz, and Guy Steele which talks about adding value types to a future version of Java. This note is a position statement rather than a fully spec'd (and adopted) proposal. However the note does give us this hint:
"Many of the above restrictions correspond to the restrictions on so-called value-based classes. In fact, it seems likely that the boxed form of every value type will be a value-based class."
which could be read as implying that there will be a relationship between value types and existing value-based classes. (Especially if you read between the lines of the Java 8 description of value-based classes.)
UPDATE - 2019/05/18
Value types didn't make it into Java 12, and they are not (yet) on the list for Java 13.
However, it is already possible to demonstrate a problem that is related to the problem that the blog post talks about:
public class BrokenSync {
private final Integer lock = 1;
public void someMethod() {
synchronized (lock) {
// do something
}
}
}
The problem is that each instance of BrokenSync
will create an Integer
instance by auto-boxing 1
. But the JLS says that Integer
objects produced by auto-boxing are not necessarily distinct objects. So, you can end up with all instances of BrokenSync
using the same Integer
object as a lock.