多线程并发编程之线程安全问题

177 阅读2分钟

可见性

什么是可见性问题

  • 在多线程当中一个线程对共享变量值的修改,不能够及时的被其他线程看到。

为什么会有可见性的问题

  • 主要原因是因为CPU指令重排序。在编译后的CPU读取的字节码文件与源文件中的代码执行顺序会不一样,CPU为了提高性能,在执行时会将指令重新排序,导致一些在源文件中的关键数据被缓存。

如何解决可见性的问题

  • 建立内存屏障。简单来说,就是一条指令,这条指令指示不要对这些代码或代码块进行重排序。在JAVA中提供了volatile关键字来指定这个变量使用内存屏障并禁止指令重排序,来保证变量不会被重排序,从而达到解决数据的可见性问题。volatile关键子只能保证可见性,不能保证原子性

关于JAVA可见性的其他说明

  1. JIT编译器
  2. volitae不能被缓存
  3. 共享变量
  4. 对于同步的规则定义
  5. 先行发生原则
  6. final关键字在JMM中的处理

原子性

什么是原子性问题

  • 在多线程当中一个线程将主内存中变量的值拷贝到私有内存中进行修改,未把修改后的值写入主内存,就已经被其他线程写入。

为什么会有原子性问题

  • 当线程将主内存中的数据读取到自己的私有内存中进行修改后,再将修改后的数据写入主内存中,这个过程不是一个CAS(硬件同步原语)操作。过程中有可能被其他线程干扰。

如何解决原子性问题

  • 使用CAS机制保证原子性,这里需要说明,CAS机制是硬件级别实现的。

关于JAVA原子性当其他说明

  1. atomic相关类
  2. unsafe实现cas机制
  3. cas的三个问题
  4. aba问题

锁相关