做公司网站都需要什么,wordpress 文章排名,深圳龙岗新楼盘开盘信息,百度不收录网站内页1、不变性 某个对象在被创建后其状态就不能被修改#xff0c;那么这个对象就称为不可变对象#xff0c;不可变对象一定是线程安全的。不可变对象很简单。他们只有一种状态#xff0c;并且该状态由构造函数来控制。 当满足以下条件时#xff0c;对象才是不可变的#xff1a… 1、不变性 某个对象在被创建后其状态就不能被修改那么这个对象就称为不可变对象不可变对象一定是线程安全的。不可变对象很简单。他们只有一种状态并且该状态由构造函数来控制。 当满足以下条件时对象才是不可变的(1)、对象创建以后其状态就不能改变(2)、对象的所有域都是final类型(3)、对象是正确创造的(在对象创建期间this引用没有溢出)。 1.1 final域 关键字final用于构造不可变对象final类型的域是不能修改的(但是final域所引用的对象是可变的那么这些引用的对象是可以修改的)即使对象是可变的通过将可变对象的某些域声明为final类型相当于告诉维护人员这些域是不可变化的。 2、正确发布一个对象 正确发布一个对象遇到的两个问题(1)引用本身要被其他线程看到(2)对象的状态要被其他线程看到。 在多线程编程中首要的原则就是要避免对象的共享因为如果没有对象的共享那么多线程编写要轻松得多但是如果要共享对象那么除了能够正确的将构造函数书写正确外如何正确的发布也是一个很重要的问题。 我们看下面的代码 1 public class Client {2 public Holder holder;3 4 public void initialize(){5 holder new Holder(42);6 }7 }8 9
10 public class Holder {
11 int n;
12 public Holder(int n) {
13 this.n n;
14 }
15 public void assertSanity() {
16 if(n ! n)
17 throw new AssertionError(This statement is false.);
18 }
19 } View Code 在Client类中Holder对象被发布了但是这是一个不正确的发布。由于可见性问题其他线程看到的Holder对象将处于不一致的状态即使在该对象的构成构函数中已经正确的该构建了不变性条件这种不正确的发布导致其他线程看到尚未创建完成的对象。主要是Holder对象的创建不是原子性的可能还未构造完成其他线程就开始调用Holder对象。 由于没有使用同步的方法来却确保Holder对象包含引用和对象状态都没有对其他线程可见因此将Holder成为未正确发布。问题不在于Holder本身而是其没有正确的发布。上面没有正确发布的可能导致的问题 别的线程对于holder字段可能会看到过时的值这样就会导致空引用或者是过时的值即使holder已经被设置了引用本身没有被别的线程看到更可怕的是对于已经更新holder及时能够看到引用的更新但是对于对象的状态看到的却可能是旧值对于上面的代码可能会抛出AssertionError异常主要是holder new Holder(42);这个代码不是原子性的可能在构造未完成时其他线程就会调用holder对象引用从而导致不可预测的结果。 2.1安全发布常用模式 要安全的发布一个对象对象的引用和对象的状态必须同时对其他线程可见。一般一个正确构造的对象构造函数不发生this逃逸可以通过如下方式来正确发布 (1)、在静态初始化函数中初始化一个对象引用 (2)、将一个对象引用保存在volatile类型的域或者是AtomicReference对象中 (3)、将对象的引用保存到某个正确构造对象的final类型的域中。 (4)、将对象的引用保存到一个由锁保护的域。 在线程安全容器内部同步意味着在将对象放到某个容器中比如Vector中将满足上面的最后一条需求。如果线程A将对象X放到一个线程安全的容器中随后线程B读取这个对象那么可以确保可以确保B看到A设置的X状态即便是这段读/写X的应用程序代码没有包含显示的同步。下面容器内提供了安全发布的保证 (1)、通过将一个键或者值放入Hashtable、synchronizedMap或者ConcurrentMap中可以安全将它发布给任何从这些容器中访问它的线程。 (2)、通过将某个元素放到Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchroizedList可以将该元素安全的发布到任何从这些容器中访问该元素的线程。 (3)、通过将元素放到BlockingQueue或者是ConcrrentLinkedQueue中可以将该元素安全的发布到任何从这些访问队列中访问该元素的线程。 通常要发布一个静态构造的对象最简单和最安全的方式是使用静态初始化器 public static Holder new Holder(42); 静态初始化器由JVM在类的初始化阶段执行由于JVM内部存在同步机制所以这种方式初始化对象都可以被安全的发布。对于可变对象安全的发布之时确保在发布当时状态的可见性而在随后的每次对象的访问时同样需要使用同步来确保修改操作的可见性。 转载于:https://www.cnblogs.com/Hxinguan/p/7471461.html