1、安全发布对象的发布与逃逸。
发布对象,使一个对象能够被当前范围之外的代码所使用。
对象逸出,一种错误的发布,当一个对象还没有构造完成时,就使它被其他线程所见。
如果不正确的发布了可变对象,会造成两种错误,首先是发布线程以外的任何线程都可以看到被发布对象的过期的值。其次呢,线程看到的被发布对象的引用是最新的,然而呢,被发布对象的状态却是过期的,如果一个对象是可变对象,那么它就要被安全发布才可以。
2、安全发布对象的四种方式。
1)、第一种,在静态初始化函数中初始化一个对象引用。
2)、第二种,将对象的引用保存到volatile类型域或者AtomicReference对象中。
3)、第三种,将对象的引用保存到某个正确构造对象的final类型域中。
4)、第四种,将对象的引用保存到一个由锁保护的域中。
2.1、懒汉模式 ,单例实例在第一次使用时进行创建,单线程运行没有问题的,但是多线程可能在getInstance出现线程不安全的情况。
1 package com.bie.concurrency.example.singleton; 2 3 import com.bie.concurrency.annoations.NotThreadSafe; 4 5 /** 6 * 7 * 8 * @Title: SingletonExample1.java 9 * @Package com.bie.concurrency.example.singleton 10 * @Description: TODO 11 * @author biehl 12 * @date 2020年1月6日 13 * @version V1.0 14 * 15 * 1、懒汉模式 ,单例实例在第一次使用时进行创建 16 * 17 * 2、单线程运行没有问题的,但是多线程可能在getInstance出现线程不安全的情况 18 * 19 * 3、第一种,在静态初始化函数中初始化一个对象引用。 20 * 21 */ 22 @NotThreadSafe 23 public class SingletonExample1 { 24 25 // 私有的默认构造方法,避免外部通过new创建对象。 26 private SingletonExample1() { 27 } 28 29 // 定义单例对象,至少保证有一个对象被创建的。 30 private static SingletonExample1 singletonExample1 = null; 31 32 // 静态工厂方法 33 public static SingletonExample1 getInstance() { 34 // 判断对象是否为null和创建对象,此处导致了线程不安全 35 if (null == singletonExample1) { 36 singletonExample1 = new SingletonExample1(); 37 } 38 return singletonExample1; 39 } 40 41 }
2.2、饿汉模式 ,单例实例在类装载时进行创建,饿汉模式是线程安全的。饿汉模式,如果单例类构造方法中没有过多的操作处理,饿汉模式是可以接受的。饿汉模式的缺点,如果单例类构造方法中存在过多的操作处理,会导致该类加载的过慢。可能会引起性能问题。
1 package com.bie.concurrency.example.singleton; 2 3 import javax.annotation.concurrent.ThreadSafe; 4 5 /** 6 * 7 * 8 * @Title: SingletonExample1.java 9 * @Package com.bie.concurrency.example.singleton 10 * @Description: TODO 11 * @author biehl 12 * @date 2020年1月6日 13 * @version V1.0 14 * 15 * 1、饿汉模式 ,单例实例在类装载时进行创建,饿汉模式是线程安全的。 16 * 17 * 2、饿汉模式,如果单例类构造方法中没有过多的操作处理,饿汉模式是可以接受的。 18 * 19 * 3、饿汉模式的缺点,如果单例类构造方法中存在过多的操作处理,会导致该类加载的过慢。可能会引起性能问题。 20 * 21 * 4、第一种,在静态初始化函数中初始化一个对象引用。 22