# CPU多级缓存
## 1. 缓存一致性(MSIE)
> MSIE:用于保证多个cpu cache之间缓存共享数据的一致。
<br>
M:被修改 S:共享 I:无效 E:独享
![image](http://upload-images.jianshu.io/upload_images/11259005-49705d5bb77a43d0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 2. 乱序执行优化
> --处理器为提高运算速度而做出违背代码原有顺序的优化。
## 3. JVM内存模型
![image](http://upload-images.jianshu.io/upload_images/11259005-e49f6bf14d93fad1?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
> --每个线程同时访问同一个对象的同一个方法,他们都会访问这个对象的成员变量,但是他们所拥有的是这个对象的私有拷贝。
![image](http://upload-images.jianshu.io/upload_images/11259005-74c3e6b76373e724?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![image](http://upload-images.jianshu.io/upload_images/11259005-fa17c09b67fcd022?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)![image](http://upload-images.jianshu.io/upload_images/11259005-41d828cf8ed0573b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)![image](http://upload-images.jianshu.io/upload_images/11259005-e5f646e60d099e45?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)![image](http://upload-images.jianshu.io/upload_images/11259005-1b97b2d14057581d?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## 4. 并发的优势与风险
![image](http://upload-images.jianshu.io/upload_images/11259005-bbab99609ab699ed?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# Atomic类
1. AtomicXXX
> 底层通过CAS(compareAndSwapInt)实现乐观锁,dowhile循环判断是否和底层记录的值一样
2. LongAdder
> 高并发情况下效率高
3. AtomicReference
>
private static AtomicReference<Integer> count = new AtomicReference<>(0);
count.compareAndSet(0, 2);
count.compareAndSet(0, 1);
count.compareAndSet(1, 3);
count.compareAndSet(2, 4);
count.compareAndSet(3, 5);
log.info("count:{}",count.get());//4
4. AtomicIntegerFiledUpdater
>
@Getter
public volatile int count = 100;
private static AtomicExample4 example4 = new AtomicExample4();
public static void main(String[] args) {
//实例指定类名和字段,字段必须通过volatile修饰,实现乐观锁
AtomicIntegerFieldUpdater<AtomicExample4> updater = AtomicIntegerFieldUpdater.newUpdater(AtomicExample4.class, "count");
if (updater.compareAndSet(example4, 100, 120)) {
log.info("update{}",example4.getCount());
}
}
5. AtomicStampedReference解决ABA问题,添加版本号
# Synchronized与Lock
![image](http://upload-images.jianshu.io/upload_images/11259005-c828ea5b69365a54?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## Synchronized
1. 可见性:解锁前,把共享变量刷新到主内存;加锁时,清空工作内存的值,并从向内存中获取最新值
## Volatile
1. 通过加入内存屏障,和禁止重排序优化,来实现可见性
2. 对Volatile变量修改时,强制刷入主内存;读取时,强制获取主内存的值,在cup指令级别加入屏障保证顺序
3. 修饰的变量不适合写操作,多于获取当前状态和DoubleCheck
## happens-before八条原则
1. 程序次序规则:单线程按书写顺序进行
2. 锁定规则:先unlock,后lock
3. volatile变量规则:先写后读
4. 传递规则:A->B,B->C,A->C
5. 线程启动规则:start()
6. 线程中断规则:interrupt()
7. 线程终结规则:join()
8. 对象终结规则:finalize()
## 线程安全性
1. 原子性:提供互斥访问
2. 可见性:一个线程对主内存的修改,可以及时的被其他线程观察到
3. 有序性:无法从hb原则推导出来,则虚拟机会进行重排序
# 发布对象
1. 发布对象:使一个对象能够被当前范围之外的代码所使用
2. 对象溢出:当一个对象还没有构造完成时,就被其他线程所见
## 安全发布对象
1. 在静态初始化函数中初始化一个对象引用
2. 将对象引用保存到volatile类型域或者AtomicReference对象中
3. 将对象的引用保存到某个正确构造对象的final类型域中
4. 将对象的引用保存到一个由锁保护的域中
## final
![image](http://upload-images.jianshu.io/upload_images/11259005-0ec36e54d56e6562?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
> Collections.unModifiableMap(map)禁止修改数据,guava里的ImmutableList.of(list)
## ThreadLocal线程封闭,规避并发
1. connection
## SDF和JodaTime
1. SDF不是线程安全
2. 使用JodaTime
>
private static DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyyMMdd");
# 同步容器
## CopyOnWriteArrayList
1. 适合读多写少
2. 读写分离,写的时候加ReentrantLock
3. 开辟空间,解决并发冲突
## CopyOnWriteArraySet
1.
## ConcurrentSkipListSet
## ConcurrentHashMap
1. 读取效率高
## ConcurrentSkipListMap
1. 高并发效率高,key有序
## J.U.C包
![image](http://upload-images.jianshu.io/upload_images/11259005-3c464d6e4f8f1014?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# AQS(AbstractQueuedSynchronizer)
## CountDownLatch 闭锁
1. 原子计数器
2. countDown()向下计数
3. await()结束计数,传入参数可提前结束
## Semapphore 信号量
1. 维护了当前访问个数
2. acquire()获取许可,可获取多个
3. release()释放许可,可释放多个
4. boolean tryAcquire()尝试获得许可
## CyclicBarrier 多线程闭锁
## ReentrantLock
1. 可重入性
2. 基于JDK实现(Synchronize基于JVM)
3. 指定公平锁和非公平锁(先等待先获得)
4. 可选择分组唤醒(Synchronize随机唤醒)
5. 可中断lock.lockInterruptibly()
6. lock()unlock()加锁解锁,unlock放在finally块
## ReentrantReadWriteLock 悲观锁
1. 可获取读锁和写锁
2. 获取写锁时,必须没有任何锁保持
## StampedLock
class Point {
private double x, y;
private final StampedLock sl = new StampedLock();
void move(double deltaX, double deltaY) { // an exclusively locked method
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
//下面看看乐观读锁案例
double distanceFromOrigin() { // A read-only method
long stamp = sl.tryOptimisticRead(); //获得一个乐观读锁
double currentX = x, currentY = y; //将两个字段读入本地局部变量
if (!sl.validate(stamp)) { //检查发出乐观读锁后同时是否有其他写锁发生?
stamp = sl.readLock(); //如果没有,我们再次获得一个读悲观锁
try {
currentX = x; // 将两个字段读入本地局部变量
currentY = y; // 将两个字段读入本地局部变量
} finally {
sl.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
//下面是悲观读锁案例
void moveIfAtOrigin(double newX, double newY) { // upgrade
// Could instead start with optimistic, not read mode
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) { //循环,检查当前状态是否符合
long ws = sl.tryConvertToWriteLock(stamp); //将读锁转为写锁
if (ws != 0L) { //这是确认转为写锁是否成功
stamp = ws; //如果成功 替换票据
x = newX; //进行状态改变
y = newY; //进行状态改变
break;
} else { //如果不能成功转换为写锁
sl.unlockRead(stamp); //我们显式释放读锁
stamp = sl.writeLock(); //显式直接进行写锁 然后再通过循环再试
}
}
} finally {
sl.unlock(stamp); //释放读锁或写锁
}
}
}
使用:
long stamp = lock.writeLock();
try{
count++;
}finally{
lock.unlock(stamp);
}
## Condition 控制AQS等待队列
1. await()等待 singal()唤醒
## FutureTask
1. 继承了Future和Runnable
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
log.info("do something in callable");
Thread.sleep(5000);
return "Done";
}
});
new Thread(futureTask).start();
log.info("do something in main");
Thread.sleep(1000);
String result = futureTask.get();
log.info("result:{}", result);
## Fork/Join框架
1. 把大任务分解成若干小任务执行
2. mapperreduce思想
3. 工作窃取算法:双端队列,先执行完毕的线程,会从其他尾部开始执行任务,进行充分并行计算
4. recursive 递归
## BlockingQueue
1. ArrayBlockingQueue有界队列,先进先出
2. DelayQueue有序
3. LinkedBlockingQueue链表结构,先进先出
4. PriorityBlockingQueue有序
5. SynchronousQueue仅容纳一个元素