安全发布对象
发布对象与对象逸出
1 package com.mmall.concurrency.demo.publish; 2 3 import com.mmall.concurrency.annoations.NotThreadSafe; 4 5 import java.util.Arrays; 6 7 @NotThreadSafe 8 public class UnsafePublish { 9 private String[] states = {"a", "b", "c"}; 10 11 public String[] getStates() { 12 return states; 13 } 14 15 public static void main(String[] args) { 16 UnsafePublish unsafePublish = new UnsafePublish(); 17 System.out.println(Arrays.toString(unsafePublish.getStates())); 18 19 unsafePublish.getStates()[0] = "d"; 20 System.out.println(Arrays.toString(unsafePublish.getStates())); 21 } 22 } 23 /* 24 [a, b, c] 25 [d, b, c] 26 */
1 package com.mmall.concurrency.demo.publish; 2 3 import com.mmall.concurrency.annoations.NotRecommend; 4 import com.mmall.concurrency.annoations.NotThreadSafe; 5 6 @NotThreadSafe 7 @NotRecommend 8 public class Escape { 9 private int thisCanBeEscape = 0; 10 11 public Escape() { 12 new InnerClass(); 13 } 14 15 private class InnerClass { 16 public InnerClass() { 17 System.out.println(Escape.this.thisCanBeEscape); 18 } 19 } 20 21 public static void main(String[] args) { 22 new Escape(); 23 } 24 } 25 /* 26 0 27 */
安全发布对象的4种方法:
1. 在静态初始化函数中初始化一个对象引用
2. 把对象的引用保存到volatile类型域或者AtomicReference对象中
3. 把对象的引用保存到某个正确构造对象的final类型域中
4. 把对象的引用保存到一个由锁保护的域中
1 package com.mmall.concurrency.demo.singleton; 2 3 import com.mmall.concurrency.annoations.NotThreadSafe; 4 5 //懒汉模式 6 @NotThreadSafe 7 public class SingletonDemo1 { 8 //私有构造函数 9 private SingletonDemo1() { 10 } 11 //单例对象 12 private static SingletonDemo1 instance = null; 13 //静态的工厂方法 加上synchronized关键字可以实现线程安全,不过并不推荐 14 public static SingletonDemo1 getInstance() { 15 if (instance == null) { 16 instance = new SingletonDemo1(); 17 } 18 return instance; 19 } 20 21 }
1 package com.mmall.concurrency.demo.singleton; 2 3 import com.mmall.concurrency.annoations.ThreadSafe; 4 5 //饿汉模式 6 @ThreadSafe 7 public class SingletonDemo2 { 8 //私有构造函数 9 private SingletonDemo2() { 10 } 11 //单例对象 12 private static SingletonDemo2 instance = new SingletonDemo2(); 13 //静态的工厂方法 14 public static SingletonDemo2 getInstance() { 15 return instance; 16 } 17 18 }
1 package com.mmall.concurrency.demo.singleton; 2 3 import com.mmall.concurrency.annoations.NotThreadSafe; 4 5 //懒汉模式 双重同步锁 6 @NotThreadSafe 7 public class SingletonDemo3 { 8 //私有构造函数 9 private SingletonDemo3() { 10 } 11 /* 12 1.memory = allocate() 分配对象的内存空间 13 2.ctorInstance() 初始化对象 14 3.instance = memory 设置instance指向刚分配的内存 15 16 JVM和cpu优化,发生了指令重排 17 18 1.memory = allocate() 分配对象的内存空间 19 3.instance = memory 设置instance指向刚分配的内存 20 2.ctorInstance() 初始化对象 21 22 */ 23 24 //单例对象 加上volatile关键字限制指令重排序可以实现线程安全 25 private static SingletonDemo3 instance = null; 26 //静态的工厂方法 27 public static SingletonDemo3 getInstance() { 28 if (instance == null) { //双重检测机制 // B 29 synchronized (SingletonDemo3.class) { //同步锁 30 if (instance == null) { 31 instance = new SingletonDemo3(); //A - 3 32 } 33 } 34 } 35 return instance; 36 } 37 }
1 package com.mmall.concurrency.demo.singleton; 2 3 import com.mmall.concurrency.annoations.ThreadSafe; 4 5 //饿汉模式 6 @ThreadSafe 7 public class SingletonDemo4 { 8 //私有构造函数 9 private SingletonDemo4() { 10 } 11 //单例对象 12 private static SingletonDemo4 instance; 13 14 static { 15 instance = new SingletonDemo4(); 16 } 17 //静态的工厂方法 18 public static SingletonDemo4 getInstance() { 19 return instance; 20 } 21 22 public static void main(String[] args) { 23 System.out.println(getInstance().hashCode()); 24 System.out.println(getInstance().hashCode()); 25 } 26 }
1 package com.mmall.concurrency.demo.singleton; 2 3 import com.mmall.concurrency.annoations.Recommend; 4 import com.mmall.concurrency.annoations.ThreadSafe; 5 6 //枚举模式:最安全 7 @ThreadSafe 8 @Recommend 9 public class SingletonDemo5 { 10 //私有构造函数 11 private SingletonDemo5() { 12 } 13 14 public static SingletonDemo5 getInstance() { 15 return Singleton.INSTANCE.getInstance(); 16 } 17 18 private enum Singleton { 19 INSTANCE; 20 private SingletonDemo5 singleton; 21 //JVM保证这个方法绝对只调用一次 22 Singleton() { 23 singleton = new SingletonDemo5(); 24 } 25 public SingletonDemo5 getInstance() { 26 return singleton; 27 } 28 } 29 }