高并发知识点



# 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仅容纳一个元素
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值