java高并发5.1 安全发布对象
发布对象
发布对象
使一个对象能够被当前范围之外的代码所使用。
在我们的日常开发中,我们经常要发布一些对象,
-
比如通过类的非私有方法返回对象的引用
-
或者通过公有静态变量发布对象。
对象逸出
一种错误的发布。当一个对象还没有构造完成时,就使它被其他线程所见。
____________________________________________________________________________
发布对象的例子:
看下面的例子: (理解一下,为什么他是线程不安全的呢?)
执行结果:
私有属性的数组被修改了, 为什么呢?
分析:
-
这个代码通过public访问级别发布了类的域,在类的任何外部的线程都可以访问这些域* (所以发布的对象是不安全的)
-
我们无法保证其他线程会不会修改这个域,从而使私有域内的值错误(上述代码中就对私有域进行了修改)
通过public方法 --->得到了private变量的引用**
____________________________________________________________________________
对象逸出的例子:
同样是线程不安全
执行结果:输出为0
分析原因:
-
这个内部类的实例里面包含了对封装实例的私有域对象的引用,在对象没有被正确构造完成之前就会被发布,有可能有不安全的因素在里面,会导致this引用在构造期间溢出的错误。
-
上述代码在函数构造过程中启动了一个线程。无论是隐式的启动还是显式的启动,都会造成这个this引用的溢出。新线程总会在所属对象构造完毕之前就已经看到它了。
-
因此要在构造函数中创建线程,那么不要启动它,而是应该采用一个专有的start或者初始化的方法统一启动线程
-
这里其实我们可以采用工厂方法和私有构造函数来完成对象创建和监听器的注册等等,这样才可以避免错误
如果不正确的发布对象会导致两种错误:
(1)发布线程意外的任何线程都可以看到被发布对象的过期的值
(2)线程看到的被发布线程的引用是最新的,然而被发布对象的状态却是过期的