什么是并发与并行?
并行:多核CPU是并行执行的,单核CPU是不可以并行执行的。
并发:多线程是并发执行的。
谈一谈对volatile的理解?
1、volatile理解:volatile是Java虚拟机提供发一种轻量级同步机制:三个特性:
1.1保证可见性;
1.2不保证原子性;
1.3禁止指令重排
指令重排:多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程使用的变量能否保证一致性是无法确定的,结果无法预测的。
2、JMM(Java内存模型)可见性、原子性、有序性
3、volatile的应用:
多线程下的单例模式:DCL(双端检锁机制)
单例模式:
/**懒汉式,线程不安全
*/
public class SingletonDemo{
private static SingletonDemo instance = null;
private SingletonDemo(){}
public static SingletonDemo getInstance(){
if(instance == null){
instance = new SingletonDemo();
}
return instance;
}
}
`public class Singleton{ //类加载时就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}}`
/**静态内部类*/
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
/**双端检测机制*/
public class Singleton {
private volatile static Singleton instance; //声明成 volatile
private Singleton (){}
public static Singleton getSingleton() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}`
什么是CAS?
1、CAS是什么:比较并交换
2、CAS底层原理:
自旋锁
unsafe类:CAS的核心类,由于Java无法直接访问底层系统,需要通过native方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe存在与sun.misc包中,内部方法操作可以像C的指针一样直接操作内存。
Unsafe类所有方法都可以直接调用操作系统底层资源执行相应任务
3、CAS是一条CPU并发原语,执行过程不允许被中断,即CAS是一条原子指令。
4、总结:比较当前工作内存中的值和主内存中的值,如果相同则执行规定操作,否则继续比较,直到主内存和工作内存中的值一致。
5、CAS的缺点:
1、循环时间长,开销大;
2、只能保证一个共享变量的原子操作;
3、引出来ABA问题
什么是原子类AtomicInteger的ABA问题,原子更新引用?
1、ABA问题是一个时间差问题,内存中的数据可能被其他线程使用操作,但是初始结果是一致的。
2、解决ABA问题:增加一种机制,修改版本号
我们知道ArrayList是线程不安全,请编写一个不安全的案例并给出解决方案
异常:java.util.ConcurrentModificationException(并发修改异常)
解决方法:List<String> list = Collections.synchronizedList(new ArrayList<>());
List<String> list = new Vector<>();
List<String> list = new CopyOnWriteArrayList<>();读写分离思想
锁
公平锁与非公平锁
1、是什么?
公平锁:是指多个线程按照申请锁的顺序来获取锁,先来后到。
Lock lock = new ReentrantLock(true);
非公平锁:是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请锁的线程比先申请的线程优 先获取锁,在高并发的情况下,有可能造成优先级反转或者饥饿现象。
Lock lock = new ReentrantLock();
可重入锁(递归锁)
1、是什么?
广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死 锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁。
在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁
自旋锁
1、是什么?
自旋锁指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,能够减少线程上下文切换的消耗,缺点是循环会消耗CPU。
独占锁(写锁)
1、只能被一个线程锁持有。对ReentrantLock 和synchronized而言都是独占锁。
共享锁(读锁)
1、改锁可以被多个线程持有
对ReentrantReadWriteLock其读锁是共享锁,写锁是独占锁。