以线程安全方式发布非线程安全对象字段

我遇到了Java并发问题。 是的,我看了几乎完全相同标题的问题,但他们似乎都在寻求微妙的不同之处。 是的,我在实践中阅读了Java Concurrency 。 是的,我可以看出为什么它是该主题的事实参考。 是的,我已经阅读了专门针对线程安全类中的发布字段的部分。 是的,我仍然会问一个关于Java的并发问题,不管我知道有人会简单地指出我那本书。

这让我很难过 – 我知道你可以通过确保具有易变性和/或同步访问的正确读/写命令,以线程安全的方式轻松发布可变原语字段,并且64位原语需要具有primefaces访问权限由于其读/写操作缺乏primefaces性。 我知道在需要在类的字段的特定“快照”上执行的代码块上使用锁。 我完全知道像AtomicLong 等好东西的原子包。

但是我仍然对将非线程安全对象作为线程安全类中的字段发布感到困惑。

从我所看到的,只要你在getter中返回对它的引用,你就可以在任何时候对调用者提供前所未有的对象内容访问权限。 此外,如果你给一个setter,你允许他们将对象引用设置为一个对象,他们可以在他们使用setter的对象之外控制它们。

无论如何我无法解决从非线程安全对象组成线程安全类而不使它们全部私有/受保护并在类中为所有非线程安全对象的所有方法创建线程安全包装器方法让该类的用户可能想要使用。 这听起来像是一个样板噩梦。

我的意思是,如果你将一个AtomicReference 返回给getter中的对象,他们可以使用.get()再次获得对它的非同步访问。

我考虑的另一种方法是让所有getter基于旧的获取非线程安全对象的新副本,这意味着修改将是无关紧要的,同样适用于setter。 但是Java有一个无可救药的复杂系统来克隆对象(浅拷贝与深拷贝和特定拷贝等),这有点让我无法做到这一点。 而且,这是非常低效的,它不会比使用像Clojure那样为不变性设计的语言更快。 事实上,考虑到这些语言允许多条不可变数据在幕后共享相同的数据,它可能会慢得多。

那么,如何以可行的方式编写已发布的非线程安全对象的线程安全类?

提前致谢。

如果对不安全对象的引用已转义到周围的线程 – 您无法阻止其他线程改变状态,因此您应该保持引用安全。 如果您需要返回复杂对象,请将数据设置为私有,引入封装访问和修改的方法并生成线程安全副本(是的,克隆很麻烦)。

试着看看http://en.wikipedia.org/wiki/Law_of_Demeter设计原理。 quote:特别是,一个对象应该避免调用另一个方法返回的成员对象的方法。 对于许多使用点作为字段标识符的现代面向对象语言,法律可简单地表述为“仅使用一个点”。 也就是说,代码abMethod()违反了a.Method()没有的规律。 举个简单的例子,当一个人想要遛狗时,指责狗的腿直接走路是愚蠢的。 相反,一个人命令狗,让它照顾自己的腿。

ps:我担心这是开放式的问题。