全站最帅😎
发布于 2021-08-25 / 849 阅读
0
0

并发编程 - 解决原子性问题

1. 何为原子性?

CPU层面一个或者多个操作在 CPU 执行的过程中不被中断的特性,称为 “原子
性”;对于日常使用的编程语言,原子性的解释可以是 多个资源间有一致性的要求,操作的中间状态对外不可见

long 型变量在 32 位机器上读写可能出现的诡异 Bug,因为 CPU 要进行两次运算,一个写高32位,一次写低32位,在多核CPU的情况下就会出现多个CPU操作同一份数据。如果我们能够保证对共享变量的修改是 互斥 的,那么就能保证原子性。Long类型bug.jpg

2. 锁模型保证原子性

我们把一段需要 互斥执行 的代码称为 临界区,线程进入到临界区前尝试对 受保护的资源 进行加锁 lock(),离开临界区执行解锁 unLock()

加锁的原则:1. 注意锁的粒度,如果锁的粒度太粗会影响执行效率。2. 切记注意锁住正确的资源,加锁错误一样会有并发问题

锁机制.jpg

2.1 synchronized锁技术

  • 基于Native方法实现,在 JDK1.5 之后得到了大量的优化;单线程访问为偏向锁,减少加锁开销,如果存在线程竞争则升级为轻量级锁,同时抹去偏向锁标识。
  • 可以修饰代码块、方法
  • 获取锁不可超时、不可中断、会导致线程阻塞(不同于JUC里面的锁),且自身占有的资源不会被释放
  • 可变对象不能用于加锁,如下代码
class SafeCalc {
  long value = 0L;
  long get() {
    synchronized (new Object()) {
      return value;
    }
  }
  void addOne() {
    synchronized (new Object()) {
      value += 1;
    }
  }
}

评论