1、谈谈你对volatile的理解
答:volatile是java虚拟机提供的轻量级的同步机制。
volatile保证可见性、不保证原子性、禁止指令重排序
2、谈谈JMM
答:JMM是java memory model,java内存模型。它是一种抽象的概念,并不真实存在。它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。
即:线程对变量的操作必须在工作内存中进行,首先将变量从主内存拷贝到自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存。
JMM对变量的可见性、有序性(禁止指令重排序)、原子性有相应规定。
3、CAS是什么?
compare and swap。比较并交换
AtomicInteger.compareAndSet
unsafe.compareAndSet
CAS依赖于Unsafe
它是一条CPU并发原语。
它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。调用Unsafe类中的CAS方法,JVM会帮我们实现出CAS汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。
CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。
乐观锁的实现方式
4、Unsafe
rt.jar中的类,使用native修饰的方法。基于该类可以直接操作特定内存的数据。
Unsaft类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存。
Unsafe类中的方法都直接调用操作系统底层资源执行相应任务。
5、CAS的缺点:
循环时间长开销很大,只能保证一个共享变量的原子操作,会引发ABA问题
6、ABA问题
多版本问题,改过一次后改回原值。
尽管结果是一致的,但是过程不一定。
解决办法:使用原子引用,AtomicReference
7、原子引用,AtomicReference
compareAndSet(A,B) 保证只能修改一次
8、原子时间戳引用,AtomicStampedReference
中间有修改过,不可以cas修改
版本getStamp,最新值:getReference。
9.ArrayList
默认size是10,扩容一半5个。
ArrayList并发访问时候,会抛出java.util.ConcurrentModificationException
new Vector<>() 和 Collections.synchronizedList(new ArrayList<>());
CopyOnWriteArrayList
10.CopyOnWriteArrayList
volatile修饰数组,ReetrantLock修饰add方法。读写分离,写时候复制,原数组废弃。
11.HashSet
会抛出java.util.ConcurrentModificationException
Collections.synchronizedSet
CopyOnWriteArraySet,内部使用CopyOnWriteArrayList
底层是HashMap, key都是PRESENT
12.HashMap
会抛出java.util.ConcurrentModificationException
使用ConcurrentHashMap,或Collections.sychronizedMap
13.公平锁和非公平锁
ReetrantLock 是可重入锁。默认是非公平锁,可以构造器设置true,为公平锁。
公平锁,就是队列,先来后到。具体是:是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到。
在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己
非公平锁,插队。是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程优先获取锁在高并发的情况下,有可能会造成优先级反转或者饥饿现象。
非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。
14.可重入锁
锁:学校门栓,加锁和解锁。
可重入锁,就是递归锁,ReetrantLock和sychronized。外层函数获得锁,内层函数仍然能获取该锁的代码。
15.自旋锁
Unsafe类+CAS思想,获取锁的线程不会立即阻塞,而是采用循环的方式尝试获取锁。这样的好处是减少线程上下文切换,缺点是循环消耗cpu
16.独占锁和共享锁
独占锁:指被锁一次只能被一个线程锁持有。对ReetrantLock和Synchronized而言都是独占锁。
共享锁:指该锁可被多个线程所持有。
对ReetrantReadWriteLock其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。
17.CountDownLatch 计数器
CountDownLatch countDownLatch = new CountDownLatch6)
countDownLatch.countDown()
countDownLatch.await()
子线程中计数器n减少为0,主线程才可以继续
18.CyclicBarrier 循环屏障
到齐了再做。
集齐7颗龙珠召唤神龙。
让一组线程到达一个屏障,也可以叫做同步点时,被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await方法
CyclicBarrier cyclicBarrier = new CyclicBarrier (7,()->func{});
cyclicBarrier .await()
19.Semaphore 信号灯
增车位。
作用:一个是共享资源互斥访问,一个是并发线程数的控制
默认非公平锁
Semaphore semaphore = new Semaphore(3,nonfair) ;//3个停车位
semaphore.acquire() 抢车位
semaphore.release()




