JUC高频面试题---由Volatile印出来的一系列问题

一、Volatile关键字的理解

volatile时java虚拟机提供的轻量级同步机制

1.1 保证可见性

轻量级volatile会及时通知各个线程主内存中变量的变化

1.2 不保证原子性

某个线程做某个具体业务时候,中间不可以被加塞或者被分割,需要完整的完成,可以与实务类比。
在这里插入图片描述
num++ 在多线程情况下是非线程安全的,去和不加synchronized来解决呢?

  • 太重量不建议用

1.3 禁止指令重排

避免多线程环境下出现乱序执行的现象
在这里插入图片描述

1.4 你在哪里使用过volatile?

单例模式:

二、JMM内存模型

它是一种抽象的概念,并不存在,他描述的是一种规范和约束规定。通过这组规定定义了程序中各个变量的访问方式。
主内存是共享内存区域,所有的县城都可以访问,线程使用必须拷贝到自己的内存空间,操作完成后再写会主内存。
线程之间无法访问对方的工作内存。
JMM规定:

  • 线程解锁前,必须把共享变量的值刷新回主内存
  • 线程加锁前,必须读取主内存的最新值到自己的工作内存
  • 枷锁和解锁是通一把锁

JMM特点:

  • 可见性
  • 原子性
  • 有序性

三、CAS

3.1 概念

CAS比较与交换CompareAndSet(),是CPU并发原语。
原语:连续,不允许中断,原子指令,不会造成线程不安全。
在这里插入图片描述
真实值与期望值相同 true 修改成功
也就是比较主内存与工作内存中的值。
Unsafe类是CAS的核心类,由于Java无法直接访问底层,需要通过native方法来访问,基于该类可以直接操作特定内存的数据。

如果使用Synchronized 在同一时间段只有一个线程使用,降低了高并发性。
如果使用CAS比较,一致性,并发性都得到了保证。

3.2 CAS缺点

没有枷锁,虽然保证了一致性,提高了并发,但是需要多次比较。

  • 循环时间长do while(),如果CAS失败,自旋,长时间不成功,给CPU带来很大的开销。
  • 只能保证一个共享变量的原子性
  • ABA问题 *****很重要!!!

3.3 原子类AtomicInteger的ABA问题谈谈?

【狸猫换太子】
在这里插入图片描述
比如右侧的线程时间比较快,从主内存中copy了A,然后改回B再写回主内存为B,10S的时候,左侧的线程比较主内存,结果没有变化,觉得并没有动,操作成功,过程是有问题的,主内存中的数据已经被右侧的线程修改了!

如何解决ABA问题?
+ 1.原子引用来解决
在这里插入图片描述
+ 2.修改版本号【类似时间戳】
演示ABA问题
在这里插入图片描述
版本号时间戳解决问题:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wyn_365/article/details/107412884