博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
局部创建对象(不正确发布:当好对象变坏时)
阅读量:6547 次
发布时间:2019-06-24

本文共 1591 字,大约阅读时间需要 5 分钟。

局部创建对象(不正确发布:当好对象变坏时)

代码清单1:

public class StuffIntoPublic {      public Holder holder;        public void initialize() {          holder = new Holder(42);      }  }

代码清单2:

public class Holder {      private int n;        public Holder(int n) {          this.n = n;      }        public void assertSanity() {          if (n != n)              throw new AssertionError("This statement is false.");      }  }

  你无法信赖局部创建对象,一个监视着处于不一致状态对象的线程,会看到尽管该对象自发布之后从未修改过,但是它的状态还是会发生突变。代码清单2的Holder使用代码清单1的不安全发布方式发布,那么除了发布线程,其他线程调用assertSanity时都可能抛出AssertionError异常。(此问题并非出在Holder类自身,而是Holder没有被正确的发布,但是将域n声明为final类型,使Holder成为不可变的,可以避免出现不正确发布的问题)

 

  原因分析如下:

  因为没有同步来确保Holder对其他线程可见,所以我们称Holder是“非正确发布的”,没有正确发布的对象会导致两种错误。首先,发布线程以外的任何线程都可以看到Holder域的过期值,因而看到的是一个null引用或者旧值,即使此刻Holder已经被赋与新值。其次,更坏的情况是,线程看到的Holder引用是最新的,然而Holder状态却是过期的。 (可以看出,在构造函数中设置的域值,应该是向这些域写入的第一个值,因此,没有“更旧”的值可以作为所谓的过期值。但是Object的构造函数会先于子类的构造函数运行,并首先向所有的域写入默认值。因此这些默认值可能成为域的过期值) 这使程序执行变得更加不可预测:线程首次读取某个域可能会看到过期值,再次读取该域会得到一个更新值,这正是assertSanity抛出AssertionError异常的原因。

 

不可变对象与初始化安全性

 

  出于不可变对象的重要性,java存储模型为共享不可变对象提供了特殊的初始化安全性的保证。

   

  另一方面,即使发布对象引用时没有使用同步,不可变对象仍然可以被安全地访问。为了获得这种初始化安全性的保证,应该满足所有不可变性的条件:不可修改的状态,所有域都是final类型的以及正确的构造。

 

  不可变类的例子:

public class Holder {      private final int n;        public Holder(int n) {          this.n = n;      }        public void assertSanity() {          if (n != n)              throw new AssertionError("This statement is false.");      }  }

 

  注意:不可变对象可以在没有额外同步的情况下,安全地用于任意线程;甚至发布它们时也不需要同步。

 

  这个保证还会延伸到一个正确创建的对象中的所有final类型域的值,没有额外的同步,final域也可以被安全地访问。然而,如果final域指向可变对象,那么访问这些对象的状态时仍然需要同步。

 

 

以上内容出  <<自并发编程实践>>

 

转载地址:http://dgedo.baihongyu.com/

你可能感兴趣的文章
Web站点风格切换的实现
查看>>
搜索实现最新的文章排序在前
查看>>
Class.forName的使用
查看>>
关于编码的思考
查看>>
delphi 进制转换
查看>>
利用JQuery给div按钮加上统一的动态效果
查看>>
步步为营 .NET 设计模式学习笔记 十六、Facade(外观模式)
查看>>
iOS程序的启动过程介绍
查看>>
DATASNAP为支持FIREDAC而增加的远程方法的数据类型TFDJSONDataSets
查看>>
“神一般存在”的印度理工学院到底有多牛?
查看>>
Hadoop2.2.0安装配置手册!完全分布式Hadoop集群搭建过程~(心血之作啊~~)
查看>>
《大话重构》
查看>>
一起谈.NET技术,WPF与混淆器
查看>>
一起谈.NET技术,C#面向对象设计模式纵横谈:Singleton 单件
查看>>
Mozilla公布Firefox 2011年开发计划
查看>>
Java访问类中private属性和方法
查看>>
UIImage扩展方法(Category)支持放大和旋转
查看>>
可复用的WPF或者Silverlight应用程序和组件设计(3)——控件级别
查看>>
Linux 查看进程和删除进程
查看>>
[Shell]Bash基本功能:通配符与特殊符号
查看>>