线程安全性

概念

  • 正确性

    • 类的行为(方法)与其规范完全一致,也就是说在多线程的场景下,类的行为返回的永远是我们所期待的结果

核心

  • 对于对象状态的访问操作的管理

    • 特别是对共享和可变的状态的访问

确保线程安全性

  • 不在线程之间共享状态变量
  • 将状态变量修改为不可变的变量
  • 访问状态变量时使用同步(加锁等)

同步

  • 关键字synchronized
  • volatile类型的变量
  • 显示锁
  • 原子变量

原子性

竞态条件

  • 概念

    • 多线程场景下不恰当的执行时序从而产生不正确的结果
  • 产生条件

    • 当某个结果的正确性取决于多线程的执行时序是,这个时候就会产生竞态条件
  • 常见类型

    • 先检查-后执行

      • 概念

        • 通过一个可能失效的数据来决定下一步的执行
      • 举例

        • 单例模式生成对象时候的if(obj==null)判断就会出现线程不安全的问题
    • 读取-修改-写入

复合操作

  • 包含了一组必须以原子方式执行的操作以确保安全性,其中先检查-后执行、读取-修改-写入就是复合操作
  • 原子的含义,一组操作语句作为一组不可分割的单元被执行

确保原子性

  • 加锁

    • 内置锁

      • 同步代码块(synchronized block)

        • 锁的对象的引用(用什么作为锁)

          • eg:synchronized修饰的方法,锁就是方法调用所在的对象
        • 锁所保护的代码块

      • 概念

        • 每个java对象都可以作为一个实现同步的锁,这个称为内置锁或者监视器锁
      • 方式

        • 每个线程在进入同步代码块之前会自动获得所,并在结束之后自动释放锁

          • 获得锁的唯一途径就是进入代码块
      • 特性

        • 可重入

          • 一个线程能够获得该线程已持有并且未释放的锁,说明获得锁的粒度是“线程”,并非请求
        • 可以免于再申请其他的锁,可以直接拿来用

    • 如何加锁?

      • 被多线程同时访问的可变状态变量的代码(路径)应该由同一个锁且只有一个锁进行保护

        • 同一个共享变量的读操作与写操作需要用同一个锁来进行保护
      • 混用两种不同的同步机制并不一定会带来好处,例如自己封装的同步代码中又使用jdk并发包底下的线程安全类可能也不是最优解

      • 当一些执行时间较长或者无法立马完成的操作,一定不要持有锁

# java 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×