我遇到了 Java 并发问题。是的,我查看了标题几乎完全相同的问题,但它们似乎都在问微妙不同的事情。是的,我读过Java 并发实践。是的,我明白为什么会这样defacto为主题提供参考。是的,我已经阅读了专门关于在线程安全类中发布字段的部分。是的,我仍然会问一个关于 Java 的并发问题,尽管我知道有人只会向我指出那本书。
但这让我感到困惑——我知道您可以通过确保具有波动性和/或同步访问的正确读/写顺序,以线程安全的方式轻松发布可变基元字段,并且 64 位基元需要具有原子访问由于其读/写操作缺乏原子性。我知道如何对需要在类字段的特定“快照”上执行的代码块使用锁。我完全了解原子包,其中包含 AtomicLong 等好东西。
但我仍然对将非线程安全对象发布为线程安全类中的字段感到困惑。
据我所知,一旦您在 getter 中返回对它的引用,您就为调用者提供了对对象内容的前所未有的访问权限,他们可以在任何时候使用它们。另外,如果您提供 setter,则允许他们将对象引用设置为他们可以在使用 setter 的对象之外控制的对象。
无论如何,我无法解决从非线程安全对象组成线程安全类而不将它们全部设为私有/受保护并在类中创建线程安全包装方法的问题all所有非线程安全对象都具有该类的用户可能想要使用的方法。这听起来就像是一场样板噩梦。
我的意思是,如果您将 AtomicReference 返回到 getter 中的对象,他们只需使用 .get() 即可再次获得对其的非同步访问。
我考虑的另一种方法是让所有 getter 基于旧对象返回非线程安全对象的新副本,这意味着修改是无关紧要的,这同样适用于 setter。但是 Java 有一个极其复杂的克隆对象系统(浅复制、深复制、特定复制等),这有点让我不敢这样做。而且,这效率很低,不会比使用以下语言更快:designed像 Clojure 一样具有不变性。事实上,考虑到此类语言允许多个不可变数据在幕后共享相同的数据,它可能会慢得多。
那么,如何以可行的方式组合已发布的非线程安全对象的线程安全类呢?
提前致谢。
如果对不安全对象的引用已逃逸到周围的线程 - 您无法采取任何措施来阻止其他线程改变状态,因此您应该保持引用的安全。如果您需要返回复杂的对象,请将数据设为私有,引入封装访问和修改的方法,并制作线程安全的副本(是的,克隆很麻烦)。
尝试看看http://en.wikipedia.org/wiki/Law_of_Demeter http://en.wikipedia.org/wiki/Law_of_Demeter设计原则。
quote:特别是,一个对象应该避免调用另一个方法返回的成员对象的方法。对于许多使用点作为字段标识符的现代面向对象语言,该法则可以简单地表述为“仅使用一个点”。也就是说,代码 a.b.Method() 违反了法律,而 a.Method() 则没有。举个简单的例子,当一个人想遛狗时,命令狗的腿直接走是愚蠢的;相反,人们命令狗并让它照顾自己的腿。
ps:恐怕这是一个开放式问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)