并发编程的安全性(2)

安全:安全的首先是正确的且是我们预期的,

正确性:某个类的行为与其规范完全一致。

在良好的规范中通常会定义各种不变性条件来约束对象的状态,以及定义各种后验条件来描述对象操作的结果。我们根据这些规范在单线程中运行获取正确的预期结果,代表这个程序的正确性,即所见即所知。

而当多个线程同时访问某个类,这个类始终能保持其正确性,我们就认为这个类是线程安全的。

(无状态对象一定是线程安全的)

原子性

原子性指操作不被中断,直到结束。

竞态条件

某个计算的正确性取决于多个线程的交替执行时序,就发生了竞态条件(是否正确看运气)。

1、先检查后执行

例如A和B相约星巴克,A到了之后看B不在,走了,刚走B来了。这个流程就发生了检查与执行不一致。

这种观察结果的失效就是大多数竞态条件的本质-基于一种可能失效的观察结果,做出判断或执行某个操作。

a、延迟初始化

public class LazyInitRace {
    private ExpensiveObject instance = null;

    public ExpensiveObject getInstance() {
        if (instance == null)
            instance = new ExpensiveObject();
        return instance;
    }
}

A与B同时初始化LazyInitRace,A、B同时getInance操作,A已经在创建对象返回前,而B刚判断对象为空准备执行,则结果是A、B分别得到不同的对象。而getInstance预期的是得到一个相同的对象。

要避免竞态的问题,就是要让检查执行成为一个原子操作。

使用锁来保护状态

访问共享状态的复合操作,都必须是原子的,在执行复合操作的时候持有一个锁,可是复合操作成为一个原子操作。

用同步来协调对某个变量的访问,那么在访问该变量所在的位置上所有操作这个变量都需要同步。

每个共享的和可变的变量都应该只由同一个锁保护。

锁不可滥用,且尽管将所有方法均使用锁,也不能保证程序的安全性

if(!vector.contains(element))
    vector.add(element);

vector.contains与vector.add都是原子操作,而上面只能称之为复合操作。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值