java程序如何确保多线程的运行安全?

线程的安全问题体现在:

  • 原子性:一个或多个操作在CPU执行过程中不被中断的特性
  • 可见性:一个线程对共享变量的修改,另一个线程能立刻看到
  • 有序性:程序执行的顺序按照代码的先后顺序执行

导致线程存在安全问题的原因:

  • 缓存导致可见性问题
  • 线程切换导致原子性问题
  • 编译优化导致的有序性问题

java给出的解决方法:

  • JDK Atomic开头的原子类、synchronized、LOCK,可以解决原子性问题
  • synchronized、volatile、LOCK,可以解决可见性问题
  • Happens-Before 规则可以解决有序性问题

Happens-Before规则:

  因为jvm会对代码进行编译优化,指令会出现重排序的情况,为了避免编译优化对并发编程安全性的影响,需要happens-before规则定义一些禁止编译优化的场景,保证并发编程的正确性。

  1. 程序顺序性规则:指的是在一个线程内,按照程序代码的顺序,前面的代码运行的结果能被后面的代码可见。
  2. 传递性规则:传递性,指的是如果A Happens-Before于B,B Happens-Before于C,则A Happens-Before于C。这个是很好理解的。用白话说就是,如果A的操作结果对B可见,B操作结果对C可见,则A的操作结果对C也是可见的。
  3. volatile变量规则:指对一个volatile变量的写操作,Happens-Before于后续对这个volatile变量的读操作。
  4. 指的是一个锁的解锁 Happens-Before 于后续对这个锁的加锁。
  5. 线程start()规则:指的是主线程A启动子线程B后,子线程B能看到主线程在启动线程B前的操作。
  6. 线程join()规则:指的是线程A调用线程B的interrupt()方法,Happens-Before 于线程B检测中断事件(也就是Thread.interrupted()方法)。这个也很容易理解。
  7. 线程的interrupt()规则:指的是线程A调用线程B的interrupt()方法,Happens-Before 于线程B检测中断事件(也就是Thread.interrupted()方法)。这个也很容易理解。
  8. finalize()规则:指的是对象的构造函数执行、结束 Happens-Before 于finalize()方法的开始。
posted @ 2019-11-18 20:04  莫等、闲  阅读(2210)  评论(0编辑  收藏  举报