并发编程-发布与逸出

发布:对象能在当前作用域之外的代码中使用。

发布方式:

1、对象引用保存到其他地方

2、public方法返回对象引用

3、引用传递到其他方法

某个不该发布的对象发布,这种情况成为逸出

封装使得程序的正确性进行分析变得可能,这也是封装最重要的意图,

安全的对象构造

构造对象的过程中不要让this引用逸出,常见的是在构造函数中启动一个线程。启动线程后,新的线程能够访问该对象的this,新的线程可能会操作一个尚未构造完成的对象,

线程封闭

将对象的访问限制在单个线程中,如此就不存在线程共享的问题,这种方式位线程封闭

线程封闭是实现线程安全最简单的方式,也是使用较多较好的方式,过多的共享对象会使得系统难以维护。

Ad-hoc线程封闭

维护线程封闭性完全有程序员承担

栈封闭

线程封闭的特例,只有通过局部变量才能访问对象,

局部变量的固有属性就是封闭在直线的线程中,他们位于执行线程的栈中,而栈是线程独占的。

ThreadLocal类

能将值与对象关联,ThreadLocal通常用于防止对可变的单实例对象或全局变量共享

某个频繁执行的操作需要一个临时对象,避免每次执行都重新分配该对象,可以使用ThreadLocal

不变性

不变对象一定是线程安全的

满足不可变对象条件:

1、对象创建后状态不能修改

2、所有域都是final

3、对象是正确创建的,this没有逸出

安全发布

不正确的发布:

public Holder holder;

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

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.");
    }
}

根据之前的可见性问题,其他线程看到的Holder对象将处于不一致的状态 。

由于没有使用同步来确保Holder对象对其他线程可见,因此Holder被称为未被正确发布-

为正确发布的对象有两个问题:

1、除了发布对象的线程外,其他线程可以看到Holder是一个失效值。

不可变对象

可在不需要额外同步情况下安全发布,

状态不可修改

所有域都是final类型

正确构造

安全发布常用模式

可变对象必须通过安全的方式发布,这意味着发布和使用该对象的线程都必须使用同步。

要安全发布一个可变对象,对象的引用及对象的状态必须同时对其他线程可见。一个正确的构造对象可通过下面几个方式发布,

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

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

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

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

发布一个竞态构造对象,最简单安全的方式就是使用静态的初始化器。

public staitc Holder holder = new Holder();

静态初始化器有JVM在类的初始化阶段执行。在jvm内部存在同步机制,这种方式是可以安全发布的

将对象的引用保存到一个由锁保护的域中这条,我们可以安全的发布ArrayList,HashMap这些不安全的对象。

concurrency库容器类提供了多种安全发布保证:

1、将键值对放入Hashtable(不怎么用了)、synchronizedMap或者concurrentMap中

2、某个元素放入vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchronizedList或synchronizedSet中

3、BlockQueue、ConcurrentLinkedQueue中,

Future、Exchanger也可以安全发布

事实不可变对象

对象在安全发布后不会修改,没有同步的情况下,安全发布是足够的,当对象引用对所有访问该对象的线程可见,对象发布时的状态对于所有线程也是可见的,并且如果对象状态不会改变,足以保证安全访问。

事实不可见对象,不仅可以简化开发,还可以减少同步提高性能。

可变对象

对象在构造后会发生修改,那么安全发布只是确保发布当时状态的可见性,对于可变对象不仅发布对象时使用同步,而且在每次对象访问时同样使用同步确保后续操作的可见性。

对象的发布取决于其可变性:

不可变对象可以任意安全发布

事实不可变对象必须通过安全机制发布。

可变对象不仅要通过安全方式发布,而且必须是线程安全的或由锁保护的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值