并发编程学习与入门-3

安全发布对象

发布与逸出

发布对象:使一个对象能够被当前范围之外的代码所使用

1
2
3
4
5
6
7
8
9
10
11
12
private String[] states = {"a", "b", "c"};
public String[] getStates() {
return states;
}

public static void main(String[] args) {
UnsafePublish unsafePublish = new UnsafePublish();
log.info("{}", Arrays.toString(unsafePublish.getStates()));

unsafePublish.getStates()[0] = "d"; // 不安全的,通过public的getStates拿到states,可以对其更改
log.info("{}", Arrays.toString(unsafePublish.getStates()));
}

对象逸出:一种错误的发布.当一个对象还没有构造完成时,就使它被其他线程所见

1
2
3
4
5
6
7
8
9
10
11
12
13
private int thisCanBeEscape = 0;
public Escape () {
new InnerClass();
}
private class InnerClass {
public InnerClass() {
log.info("{}", Escape.this.thisCanBeEscape);
}
}

public static void main(String[] args) {
new Escape();
}

安全发布对象

有 4 种方法安全发布对象,比如单例模式的饿汉模式(线程安全),普通懒汉模式(线程不安全),懒汉双重锁检验模式(线程不安全),饿汉静态代码库模式(线程安全,注意静态域和静态代码块的执行先后顺序),懒汉双重锁检验+volatile 禁止指令重排序模式(线程安全),枚举模式(线程安全)

1.在静态初始化函数中初始化一个对象的引用

2.将对象的引用保存到 volatile 类型域或者 AtomicReference 对象中

3.将对象的引用保存到某个正确构造对象的 final 类型域中

4.将对象的引用保存到由一个锁保护的域中