文档说你不应该锁定基于值的Java类的实例,例如Optional
因为代码
如果它试图将两个引用区分为基于值的类的相等值,则可能产生不可预测的结果......间接地通过对同步的诉求......
为什么Java的基于价值的类不能被序列化?断言
因为未来的JVM实现可能不会使用对象标头和基于值的类的引用指针,所以一些限制很明显.(例如,没有锁定JVM必须不支持的标识.锁定的引用可以被删除并在以后被另一个替换,这使得释放锁定毫无意义并将导致死锁).
IE认为该禁令是面向未来的.但是这个断言没有参考.
如果以未来为基础,我想参考它.如果没有,我想了解基于价值的对象是什么基础Object
.
编辑
顺便说一句,我理解不要锁定Integers和其他原始包装类的原因; 他们可能会被缓存.但是我找不到任何文档说基于价值的类,以及整数,等等.基于价值观,它们不是基于价值的类.IE 可选的JavaDocs等.明确地说
这是一个基于价值的课程
对于Integer,等等,情况并非如此.
以下是Nicolai Parlog关于基于价值的课程的博客文章:
在Java 8中,值类型前面是基于值的类.它们在未来的精确关系尚不清楚,但它可能类似于盒装和未装箱的原语(例如Integer和int).此外,编译器可能可以自由地在两者之间切换以提高性能.恰好来回切换,即删除并稍后重新创建引用,也禁止将基于身份的机制应用于基于值的类.
尼古拉所说的是这样的:
将来,编译器可能会以不保留对象标识的方式执行在值和基于值的类之间透明转换的事情.
某些事物("基于身份的机制")取决于对象身份.示例包括==
引用的语义,标识哈希码,基元锁定和对象序列化.
对于那些事情,透明翻译可能不透明.
在原始锁定的情况下,担心的是可能发生类似以下序列的事情.
创建基于值的类的实例.
该实例将在幕后转换为值.
然后转换回值,给出不同的对象.
如果两个线程然后使用"实例"作为原始锁,他们可能不知道事实上实际上有两个对象(现在).如果他们接着尝试synchronize
,他们会(可能)锁定不同的对象.这意味着无论锁定意图保护的状态如何,都不会互相排斥.
如果您没有锁定基于价值的课程,您将不必担心将来的潜在危险.
但请注意,Nicolai的博客文章是一个人对Java 10或更高版本可能发生的事情的猜测.
顺便说一句,我理解不要锁定Integers和其他原始包装类的原因; 他们可能会被缓存.
缓存本身不是问题,而是一种引发问题的机制.真正的问题是难以推断锁定对象的对象身份,因此锁定状态是否合理.
使用原始包装器,装箱和拆箱的语义会增加对象身份的不确定性.展望未来,提出的值类型< - >对象转换将是这种不确定性的另一个来源.
上述博客基于2014年4月的"价值观状态".John Rose,Brian Goetz和Guy Steele谈到了为未来版本的Java添加价值类型.本说明是一个立场声明,而不是完全规范(和采纳)的提案.但是这个说明确实给了我们这个提示:
"上述许多限制都与对所谓的基于价值的类别的限制相对应.事实上,每种价值类型的盒装形式似乎都是基于价值的类别. "
可以理解为暗示价值类型与现有的基于价值的类之间存在关系.(特别是如果您在基于值的类的Java 8描述的行之间阅读.)