zoukankan      html  css  js  c++  java
  • JAVA JUC 李贺飞

    1.volatile关键字与内存可见性

    本质是写的东西没有同步到读缓存

    主线程没有更新缓存数据的时间,所以内存里的改动同步不过来

    一直读的的缓存里的数据,内存的数据被写了还是读不到

    同步锁可以解决,但是效率低

    volatile:多个线程共享内存数据,保证内存中的数据是可见的。使用内存障碍,保证从主存拿数据

    volaile修饰以后,jvm不能重排序了,相较于synchronize轻量级。不需要挂起线程可以一直执行,没有挂起、恢复消耗

    但是

    • 没有互斥性
    • 不能保证变量的原子性(不可分割)

    2.原子变量与CAS算法

    本质是写的过程被分割

    i++ 读改写三步,可能保证内存可见性,但是写内存同步数据,无法互斥,会有重复操作污染数据。i++操作被分割开来,没有原子性了

    同时写内存,两条线一样的值同时发生改变成一样的,后写的覆盖了先写的

    juc的atomic包

     多个线程同时先从内存读一个数值,当做A,传进去,进行操作的从内存读一下V,一样就设置为更新值B 。读取内存和比较更新是原子操作不可分割,硬件支持

     这就保证了,同时操作,只有一个会成功

     效率比锁高,失败了就重试,不会阻塞流程

    3.模拟CAS算法

     

    3.ConcurrentHashMap锁分段机制

     HashTable整个方法执行的收都带锁,具有隐患:复合操作可能被切割,执行一半暂停,回来后状态变了,所以内部加锁没有用,要整个操作加锁。此外并行变串行,效率更低

    复合操作本质上是一句话的事情分为两个方法执行,被切割非原子 

     ConcurrentHashMap给数据分段加锁,16个段16把锁

     1.8用CAS替代分段锁

    全体方法加锁可以使用Collections.synchronizedList

    这样在使用迭代器访问并修改集合会有并发修改异常。

     因为迭代next和add操作被切割,写入的时候别人可能在读东西,一写之后再读取就出错(因为可能加在头部,再读迭代器指针就对不上,还读了上一个)。在迭代的过程中,添加和删除元素都会报错,通过modCount这个变量来校验

     使用CopyOnWriteArrayList解决,每次写入时复制新的列表再添加,读的时候读取旧的列表,两不相干。适合读操作多的时候

    4.CountDownLatch,闭锁

     

     

     

     

     5.创建线程的第三种方式,实现Callable接口

     

     

     Callable接口给FutureTask,FutureTask给Thread。FutureTask的get可以实现闭锁效果,等待Callable的call方法执行完再获取结果

     Future实现了Runnable接口

     7.同步锁

     

     有风险,要在finally里调用,不是百分百被调用

     

    8.生产者消费者案例:虚假唤醒

     生产者不停地发数据,消费者不停地接数据,没有等待,可能过度生产与消费

    如果用if esle而不是if结构,会有以下问题

    B缺

    A

    B

    B缺

    A

    A卡住等待唤醒

    本质是B跑的比较快,消费完了马上等待生产但又退出

    解决办法是等待、通知后直接进行操作,不要分开,AB或者BA有序

    wait和notifyAll

    所以要加入等待唤醒机制,生产满了等待,生产了通知,消费完了等待,消费了通知

     虚假唤醒:多个等待,一次唤醒后多个源做同一操作,超出了限制。wait要在循环中使用,不要用if用while,这样多一次判断,A、B线程同时等待,A线程执行了B线程可以在条件不满足的时候限制不要顺序执行重新等待。

    注意:当线程在某个条件变量下等待时,即使其他线程没有broadcast or signaled 这个条件变量,该线程仍然可能被唤醒,在多核处理器系统下,使条件变量完全可以预测会降低系统的性能,而导致虚假唤醒的几率又很小 

    在操作系统底层"唤醒"的实现机制就注定虚假唤醒的存在,设计者们不解决这个问题的原因是

    1. 修复这个问题会导致系统性能下降,性价比太低
    2. 即使修复了这个问题,由于同步问题的存在,仍然要将wait()放进循环里.

     8.Condition控制线程通信

     

     10.线程按需交替

    三个线程按序执行,每个线程执行前while判断条件,唤醒了满足条件就往下走,唤醒其他条件。这个过程加锁,await会临时解锁

     11.ReadWriteLock读写锁

    读写分离

    乐观锁

    同时读不加锁

     

    12.线程八锁

     

     13.线程池

     Executor就是线程池

     Executors是工厂工具类,用这个来创建线程池,不要直接创建

     

     

     14.线程池调度

    15.ForkJoinPool分支/合并框架 工作窃取

     

     

     

     

    1.读不到写的东西

    2.多个写错乱

    3.读写并发读错乱

  • 相关阅读:
    GetWindowThreadProcessId
    为什么要学制作外挂
    博客系统架构对比分析
    C# 数据库访问通用类 (ADO.NET)
    转:配置 SQL Server 2005 远程调试存储过程
    腾讯QQ空间g_tk算法
    BurstNET的linux vps 安装Kloxo面板后一切正常 今天重启导致错误Could not connect to Mysql server
    service的生命周期回调方法
    服务的生命周期回调方法
    点阵字库在JAVA中的实现
  • 原文地址:https://www.cnblogs.com/cascle/p/15406093.html
Copyright © 2011-2022 走看看