我在Java并发方面遇到了问题。是的,我看过几乎相同标题的问题,但它们似乎都在询问微妙的不同之处。是的,我读过《Java并发编程实战》。是的,我能理解为什么它是该主题的事实上的参考书。是的,我已经阅读了特别介绍线程安全类中字段发布的部分。但是,尽管我知道有人会简单地指向那本书,我仍然要在Java上提出一个并发问题。
但这让我困惑了 - 我知道你可以通过确保正确的读/写顺序使用易失性和/或同步访问来轻松地以线程安全的方式发布可变原始字段,并且由于其读/写操作的缺乏原子性,64位原语需要具有原子访问。我知道关于在需要在类的字段的特定“快照”上执行的代码块上使用锁定。我完全了解具有诸如AtomicLong<>等好处的原子包。
但是,对于在线程安全类中作为字段发布非线程安全对象仍感到困惑。
据我所见,一旦您在getter中返回对它的引用,您就已经向调用者提供了对对象内容的无限制访问,他们可以在任何时候使用它。此外,如果您提供了setter,则允许他们将对象引用设置为可能在使用setter的对象之外控制的对象。
我无法想出一种将非线程安全对象组合成线程安全类的方法,而不需要使它们全部变为私有/受保护,并为类中用户可能想要使用的所有非线程安全对象的方法创建线程安全包装方法。这听起来就像是一个样板文件噩梦。
我的意思是,如果您在getter中返回AtomicReference<>以获取对象,则可以使用.get()再次获得非同步访问。
我考虑的另一种方式是让所有getter基于旧值返回非线程安全对象的新副本,这意味着修改将是无关紧要的,setter也是如此。但是,Java具有一个令人绝望的对象克隆系统(浅拷贝vs深拷贝vs特定复制等),这让我对此感到厌烦。此外,这太低效了,与像Clojure这样“设计”为不可变性的语言相比,它不会更快。实际上,鉴于这些语言允许多个不可变数据共享背后的相同数据,它可能会慢得多。
那么,如何以可行的方式组合发布的非线程安全对象的线程安全类?
提前感谢。
但这让我困惑了 - 我知道你可以通过确保正确的读/写顺序使用易失性和/或同步访问来轻松地以线程安全的方式发布可变原始字段,并且由于其读/写操作的缺乏原子性,64位原语需要具有原子访问。我知道关于在需要在类的字段的特定“快照”上执行的代码块上使用锁定。我完全了解具有诸如AtomicLong<>等好处的原子包。
但是,对于在线程安全类中作为字段发布非线程安全对象仍感到困惑。
据我所见,一旦您在getter中返回对它的引用,您就已经向调用者提供了对对象内容的无限制访问,他们可以在任何时候使用它。此外,如果您提供了setter,则允许他们将对象引用设置为可能在使用setter的对象之外控制的对象。
我无法想出一种将非线程安全对象组合成线程安全类的方法,而不需要使它们全部变为私有/受保护,并为类中用户可能想要使用的所有非线程安全对象的方法创建线程安全包装方法。这听起来就像是一个样板文件噩梦。
我的意思是,如果您在getter中返回AtomicReference<>以获取对象,则可以使用.get()再次获得非同步访问。
我考虑的另一种方式是让所有getter基于旧值返回非线程安全对象的新副本,这意味着修改将是无关紧要的,setter也是如此。但是,Java具有一个令人绝望的对象克隆系统(浅拷贝vs深拷贝vs特定复制等),这让我对此感到厌烦。此外,这太低效了,与像Clojure这样“设计”为不可变性的语言相比,它不会更快。实际上,鉴于这些语言允许多个不可变数据共享背后的相同数据,它可能会慢得多。
那么,如何以可行的方式组合发布的非线程安全对象的线程安全类?
提前感谢。