并发编程 线程安全——Java锁概念

Java锁概念

在Java中 保证线程安全的方案分为两种:同步、无同步、

造成线程安全问题的原因就是:多线程情况下共享变量的写操作不安全 所以解决方案也就是针对共享的变量进行的 同步共享变量 或者 不同步共享变量

同步:

  • 互斥(阻塞):互斥是实现同步的一种手段 属于悲观的并发策略

    多线程并发访问共享数据时 保证共享数据在同一时刻只被一个线程使用 临界区、互斥量和信号量都是主要的互斥实现方式

    Java中实现互斥的手段:

    • synchronized 关键字
    • lock 接口

    互斥最主要的问题就是进行线程阻塞和唤醒所带来的性能问题

  • 非阻塞:基于冲突检测的乐观并发策略

    非阻塞的同步 其实就是在多线程访问共享变量的时候 先操作的线程会成功 后面的线程会失败 而失败的线程并不会阻塞挂起 而实采取其他的补偿措施 比如不断重试直到成功

    非阻塞的实现 CAS:

    • CAS指令需要有3个操作数,分别是内存地址(在java中理解为变量的内存地址,用V表示)、旧的预期值(用A表示)和新值(用B表示)
    • CAS指令执行时,CAS指令指令时,当且仅当V处的值符合旧预期值A时,处理器用B更新V处的值,否则它就不执行更新,但是无论是否更新了V处的值,都会返回V的旧值,上述的处理过程是一个原子操作。

    CAS的缺点:

    • ABA问题:因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。

      ABA问题的解决思路:使用版本号 记录修改次数

    在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的:

    • 基本类型

      • AtomicBoolean - 布尔类型原子类

      • AtomicInteger - 整型原子类

      • AtomicLong - 长整型原子类

        .......

无同步:

  • 对象不共享

    直接不使用共享变量

  • 不可变对象

    多线程对共享变量只能进行读操作

  • 线程本地变量

    直接把变量交给线程封闭起来 这样也不会被其他线程共享 自然也就不会有安全问题

总结:

  • Java中线程安全的解决方案可以简单的理解为 同步 不同步 两种 --> 针对共享变量
  • 在同步方案中又分为 互斥同步(悲观实现) 和 非阻塞同步(乐观实现) 两种 --> 针对同步方式
  • 而不同步方案 其实就是只对共享变量进行读操作 或者直接没有共享变量 --> 针对程序设计
posted @ 2021-08-12 10:06  熏晴微穗  阅读(46)  评论(0编辑  收藏  举报