01线性安全性

线性安全性

要编写线性安全的代码,核心在于要对状态访问操作进行管理,特别是共享的和可变的状态:

“状态”指存储变量中的数据

“共享”指能被多个线程同时访问

“可变”指可被修改

如果多个线程同时访问一个可变的变量,那么程序就会出现问题,有三种方法可以修复:

  1. 变量不共享
  2. 变量不可变
  3. 访问时使用同步

程序的封装性(私有域)越好,就越容易实现线程安全性

什么是线程安全性?

线程安全性是状态相关的,可能是应用于一个对象,也可能应用于一个程序。

在线性安全性的概念中,最核心的是正确性,什么是正确性?

良好的规范是定义一些不变性条件和后验条件来描述“是否正确”。但是一般情况下都不会去按照这个规范,而且通过“类的代码能正确的工作”来判断。单线程下这种“正确工作”可以表现为“所见即所知”,但多线程下时,是否能“正确的工作”往往无法直观的去判断。

定义:被多个线程访问,类能否正确的工作。

无状态的对象一定是线性安全的

原子性

一个不可分割的操作是一个原子操作

多线程下,由于原子性,会导致类无法正确的工作(尽管在单线程中看起来正常)

竞态条件:

当两个线程竞争同一资源时,由于不恰当的执行时序会出现错误的结果,常见的竞态条件如“先检查后执行”、“读取—修改—写入”,其本质是由于基于一个失效的状态进行后续的操作

复合操作?

复合操作是包含了一组必须以原子方式执行的操作以确保线程安全。

意味着:如果复合操作不易原子方式执行,则会有线程安全问题

如c++

在一些简单场合可以使用原子类 Atomic 系列来使用符合操作的原子性,从而实现线程安全,但是使用Atomic 并不能保证类的线性安全性,复杂的情形下还是需要使用锁来实现。

可重入锁以及实现:

执行锁的线程可以重复执行自身

互斥计数器:0表示无线程持有,占有后变更为1,重入后+1,跳出后-1

可重入解决什么问题?

解决子类同步代码调用本类或父类中的其他同步代码,否则会死锁

线程带来的问题:

  1. 安全性问题:程序出现错误结果,如竞态条件
  2. 活跃性问题:程序没出现正确结果,如死锁,饥饿
  3. 性能问题:正确的结果出现的很晚

本文标题:01线性安全性

文章作者:Sun

发布时间:2020年07月25日 - 18:07

最后更新:2020年08月07日 - 17:08

原始链接:https://sunyi720.github.io/2020/07/25/Java并发编程/01线程安全性/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。