java面试 (12)- Valiolate原理?是线程安全的吗?

刘大飞 / 2023-05-28 / 原文

1:导致线程问题的原因:

  抢占式执行

  多个线程同时修改了同一个变量

  非原子性操作

  内存可见性问题

  指令重排问题

2:并发编程三大特性

  可见性(读线程不能及时的读取到其他线程写入的最新值,主要是CPU存在高速缓存,所以会有数据不一致的问题)

  原子性

  有序性

3:volatile关键字

        volatile解决了内存可见性和指令重排序的问题

    写volatile变量:改变线程工作内存中的valatile变量的值,会立即从工作内存刷新到主内存中,

       新值对所有线程立即更新。

              读volatile变量:先从主内存读取volatile变量的最新值到线程的工作内存中,再从工作内存中读取volatile变量的副本值。

              在多线程环境下volatile修饰的变量值一定是最新的。

              volatile避免了指令重排优化(在单线程的情况下,指令重排优化没有问题,但是多线程的情况下有有问题),实现了有序性。

          ( 内存屏障(也叫内存栅栏):一组处理器指定,用于实现对内存操作的顺序限制)

 

 

  内存屏障(Memory Barrier)是计算机系统中用于控制内存访问顺序的一种机制。在多线程编程中,由于线程之间的并发执行,对共享内存的访问可能会出现不确定的结果,例如数据竞争(Data Race)和内存可见性(Memory Visibility)问题。内存屏障的作用是通过限制和约束内存访问的顺序,来解决这些问题。

  内存屏障可以分为两种类型:读屏障(Read Barrier)和写屏障(Write Barrier)。读屏障用于保证对共享数据的读取操作不会读取到旧的、过时的值,而写屏障用于确保对共享数据的写入操作对其他线程是可见的。

  读屏障(也称为加载屏障或获取屏障)会阻止任何后续的读操作重排到该屏障之前,以确保读操作获得的值是最新的。这样可以避免读取到过时的数据,保证读取操作的正确性。

  写屏障(也称为存储屏障或释放屏障)会阻止任何前面的写操作重排到该屏障之后,以确保写操作对其他线程是可见的。这样可以保证写入操作的结果对其他线程是可见的,并避免写入操作和后续的读操作重排。

  内存屏障在多线程编程中扮演重要的角色,它们可以通过指令级别的屏障(如CPU指令)或高级的同步原语(如互斥锁、信号量等)来实现。程序员可以使用内存屏障来显式地控制内存操作的顺序,从而避免数据竞争和内存可见性问题,保证多线程程序的正确性和一致性。