到底什么才是对象发布?为什么逸出会产生线程安全问题?

2020-12-21 15:13:12 +08:00
 zhao1014

看了书上说的概念有点模糊不清,最好是能用代码举例说明,谢谢大佬们!

1822 次点击
所在节点    Java
11 条回复
zoharSoul
2020-12-21 15:49:04 +08:00
没听说过这两个词....

带点上下文呗?
Chinsung
2020-12-21 18:09:13 +08:00
什么书啊。。。。没听过这个概念。
第二个到时候有沾点边的,好像是指的某个对象本身不是 thread safe 的,但是因为一些编程上的错误导致其他线程可以访问到,导致线程安全问题吧。
zhao1014
2020-12-21 18:23:29 +08:00
@zoharSoul
@Chinsung
是的,并发编程相关。我看的书是《 Java 多线程编程实战指南》作者:黄文海,在《 Java 并发编程实战》中也有对象发布和逸出的概念。

又重新翻了一下书,感觉已经大致理解了。

一个对象可被作用域之外的代码获取就称为对象发布,例如创建了一个私有成员,但在 public
方法中作为返回值返回。

多线程环境中对象发布的问题在于,可能存在两个线程,一个线程创建了该类的对象,而另一个线程则通过发布渠道(例如上述的 public 方法)访问该对象的成员。

如果 JIT 或 处理器执行了指令重排序,导致成员的初始化被重排序到引用赋值之后,那么第二个线程使用该对象时,该对象还没有初始化完毕,即该对象的成员可能为 null (默认值)
chendy
2020-12-21 18:31:00 +08:00
这个翻译一看就是《 Java 并发编程实践》……
原文:
**Publishing** an object means making it available to code outside of its current scope
An object that is published when it should not have been is said to have **escaped**
把对象给别人用就是“发布”,把不该发布的东西发布了就叫“逃逸”
举个例子:Collections.synchronizedCollection 会“发布”一个线程安全的 Collection,但是如果代码里有其他地方还能访问和操作其内部线程不安全的 Collection,就叫“逃逸”
zhao1014
2020-12-21 18:31:20 +08:00
@zoharSoul
@Chinsung
对象的初始化 和 对象的使用 由两条线成同时执行
zhao1014
2020-12-21 18:32:38 +08:00
@chendy 实际上是这本《 Java 多线程编程实战指南》
hyqCrystal
2020-12-22 09:23:48 +08:00
我的理解 对象发布理解为 提供外界可访问的实例对象
可以是静态初始化对象 也可以提供方法返回对象 等

发布实例对象 提供外界访问
thinkmore
2020-12-22 10:25:14 +08:00
应该是对象安全发布。


比如你写了一个方法返回 List<User>,然后其他人对这个集合中的对象做了修改,而你也在使用这个集合中的 user,就会导致他的修改影响了你的数据。

这就是逃逸。


那么如何安全发布呢?

还是上面那个例子,你可以返回 Collections.unmonifiedList 或者根据你的业务情况进行具体操作
thinkmore
2020-12-22 10:28:06 +08:00
https://generalthink.github.io/2016/09/21/talk-thread-safe/ 可以参考下我这篇博客中安全的发布对象那一部分
zhao1014
2020-12-22 11:04:35 +08:00
@thinkmore 不戳,jvm 与 硬件的联系学到了,图片我可以用到自己的笔记里吗?
thinkmore
2020-12-25 09:50:09 +08:00
@zhao1014 可以的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/737506

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX