Java多线程之共享变量的内存不可见性

共享变量的内存不可见性

多线程的内存模型

线程独有的工作内存(线程缓存 = > 提高工作效率)——所有线程共享的主内存

线程读取在主内存的成员变量,即共享变量的过程:

    1. 线程的工作内存会去读取主内存的成员变量并保存副本
    2. 线程在工作内存中修改副本
    3. 将修改后的副本的值推送给主内存并改写主内存中该变量的值
    4. 主内存成员变量修改后的值不会主动推给其他线程(各线程的内存独有),这就会造成线程的工作内存的共享变量的不同步

现有问题:各个线程的工作内存不可见

描述:A线程读取了共享变量num,此时B线程修改了共享变量为num+1,并推送给主内存改写,但是主内存不会主动推送给A线程,于是A和B的共享变量就会出现不同步!

解决方法:synchronized(同步代码块/同步方法=> 加锁 同步共享变量 ) 、volatile => 同步共享变量

volatile: Java关键字使得主内存的共享变量每经过一次修改都会推送给其他线程,让其他线程修改其工作内存中的副本!

synchronized 与 volatile的区别 / 不同点

  1. volatile 是轻量级的同步策略,用于修饰基本类型的变量;

    synchronized 是重量级的同步策略,基于对象的同步锁=> 锁的是对象/Class

  2. volatile 不具备互斥性,多个线程可以同时访问共享变量;

    synchronized 是互斥锁,具备互斥性,在加锁的同步代码块中只能有一个线程访问共享变量;

  3. volatile不能保证变量的原子性,即一组对共享变量的操作不具备事务 => 要么全部完成,要么全部不完成!

    synchronized 可以保证变量的原子性,即在被锁的代码块中只能允许一个线程去执行对共享变量的操作,其他需要执行这组操作的线程会进入阻塞状态,等待当前线程完成并释放锁。

内存不可见的本质:线程之间有互相独立的缓存区,当多个线程对共享数据进行操作时,其操作彼此不可见!

使用volatile之后 ,所有线程对共享变量的操作都相当于在主内存中完成,即不再存在操作的不可见,此时所有线程操作的变量位于主内存

posted @ 2021-07-15 16:17  夕立君  阅读(318)  评论(0编辑  收藏  举报