高频知识点总结 - 02

高频知识点总结 - 02

1.谈谈对volatile的理解

volatile 是 JVM 提供的一种轻量级的同步机制,它能够保证线程之间的可见性、不能保证原子性、禁止指令重排(保证有序性)。

下面补充一个概念:JMM(java money model)Java 内存模型

1.1 JMM

  • JMM 本身是一种抽象的概念,并不是真实存在,**它描述的是一组规则或规范,**通过这个规范定义了程序中各个变量(包括实例字段、静态字段和构成数组对象的元素)的访问方式

  • JMM 本身要求可见性、原子性、有序性

  • JMM 是 Java 内存模型。每一个线程都有自己的工作内存,但是所有的共享变量都是存在主内存中(电脑上的物理内存),当线程要操作数据时,会先将主内存中的数据复制一份到工作内存,在操作处理完以后,在更新到主内存中

  • 本身线程自己操作是对其他线程不可见的,并且线程之间无权互相访问,线程之间的通信(数据传递)必须通过主内存来实现

  • 可见性就是当前线程在将从主内存取出的值更新将要刷回主内存时,会通知其他线程自己已将主内存中的值更新

1.1.1 JMM关于同步的规定
  1. 线程解锁前,必须把共享变量的值刷新回主内存
  2. 线程加锁前,必须读取主内存中的最新值到自己的工作内存
  3. 加锁解锁是同一把锁并且加了多少把锁就要进行解锁多少次,成对出现

1.2 可见性实例演示

/*
* - 这里可以看到在int i 前面没有加上volatile修饰
* - 虽然线程已经将值修改,但是主线程并不知道值已经修改,则会一直处于等待状态
* 解决办法:在int i 前面加上volatile修饰,保证可见性
* */
public class VolatileDemo {
   
    public static void main(String[] args) {
   
        Volatile01 volatile01 = new Volatile01();

        new Thread(() -> {
   
            System.out.println(Thread.currentThread().getName()+"线程运行");

            try {
   
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }

            volatile01.add();
            System.out.println(Thread.currentThread().getName()+"修改值");

        },"线程一").start();

        while (volatile01.i == 10){
   

        }

        System.out.println(Thread.currentThread().getName()+"执行完毕");
    }
}

class Volatile01{
   
    int i = 10;

    public void add(){
   
        i = 60;
    }
}

1.2 原子性

在执行一系列的语句中,要么语句都成功,要么都失败。

1.3 volatile不具有原子性和解决办法

public class VolatileDemo02 {
   
    public static void main(String[] args) {
   
        Demo2 demo2 = new Demo2();

        for (int i = 0; i < 20; i++) {
   
            new Thread(() -> {
   
                for (int j = 0; j < 1000; j++) {
   
                    demo2.addV();
                }
            },String.valueOf(i)).start();
        }

        for (int i = 0; i < 20; i++) {
   
            new Thread(() -> {
   
                for (int j = 0; j < 1000; j++) {
   
                    demo2.addAtomic();
                }
            },String.valueOf(i)).start();
        }

        while (Thread.activeCount() > 2){
   
            Thread.yield();
        }

        /*
        * 当前在i前面加了volatile修饰词但是最终运行的结果到不了20000
        * 这是因为,出现了线程中写丢失,如果第一时间通知了其他线程值已经修改,但是线程写入主内存
        * 更新的速度太快,可能还没有接收到更改的通知,就又进行了一次主内存更新,这时就会出现重复更新
        * */
        System.out.println(demo2.i);
        /*
        * 解决方式
        * - 通过原子类来解决
        * */
        System.out.println(demo2.atomicInteger);
    }
}

// 解决办法
class Demo2{
   
    volatile int i = 0;

    public void addV(){
   
        i++;
    }

    // new AtomicInteger() 括号中没有定义则默认值为0
    AtomicInteger atomicInteger = new AtomicInteger
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值