【多线程】Volatile 线程间变量可见

    xiaoxiao2025-06-20  14

    文章目录

    1. 线程间如何共享数据2. 线程间变量为什么不可见3.如何使线程间变量可见3.1 final变量3.2synchronized3.3 volatile 4. synchronzied与volatile比较

    1. 线程间如何共享数据

      使用全局变量或共享对象

    2. 线程间变量为什么不可见

      归根原因是由Java内存模型引起的,Java内存模型及操作规范:

    共享变量必须存放在工作内存中线程有自己的工作内存, 线程只可操作自己的工作内存线程要想操作共享变量,需要从主内存中读取到工作内存,改变值后从工作内存同步到主内存中

      根据上面描述,会出现这么一个问题:线程1已经从主内存读取变量a=1到工作内存中去了,但是在更改a=a+1后未更新到主内存之前,线程2又从主内存中读取了变量a=1,此时想想必然会引起数据不一致

    主内存和工作内存之间交互遵从同步交互协议,规定了8中原子操作:

    lock锁定:将主内存中的变量锁定,为一个线程所独占unlock解锁:将lock假的锁定接触,此时其他线程有机会访问此变量read读取:作用于主内存变量,将主内存中的变量读取到工作内存当中去load载入:作用于工作内存变量,将read读取到的值保存到工作内存中的变量副本中use使用:作用于工作内存变量,将值传递给线程的代码执行引擎assign赋值:作用于工作内存变量,将执行引擎处理返回的值重新赋值给变量副本store存储:作用于工作内存变量,将变量副本的值传递给主内存中write写入:作用于主内存变量,将store传送过来的值写入到主内存的共享变量中

    注意: 每一步是原子操作,但是这8不不是一个原子操作

    3.如何使线程间变量可见

    3.1 final变量

      变量本来就是不可改变的,不存在改变,所以不同线程间看到的数据永远一样

    3.2synchronized

    synchronized语义规范:

    进入同步块之前,先清空工作内存中的共享变量,从主内存中重新加载解锁前必须把修改的共享变量同步回主内存

    synchronized是如何做到线程安全的:

    锁机制保护共享资源,只有获得锁的线程才可操作共享资源synchronized语义规范保证了修改的共享资源后,会同步回主内存,做到了线程安全

    综上:synchronized既实现了互斥性,也实现了可见性

    3.3 volatile

    使用场景

    通过共享变量控制其它线程加volatile修饰的变量所在的块不会进行指令重排优化(防止指令重排后,会出现抛空指针异常)

    4. synchronzied与volatile比较

      volatile 使用简单,性能也好,但是由于上面提到的同步交互协议中的8不操作不是一个整体的原子操作,会出现数据不一致问题,所以如果要保证数据的可见性和一致性,就要用synchronzied了

    最新回复(0)