J.U.C学习总结

[toc]

java 内存模型 Java memory model jMM

image.png
image.png

java 内存八种操作

image.png

lock >read > load > use> assing > store >write >unlock

线程安全

  • 定义
    当多个线程访问某一个类时,不管运行时环境何种调度方式或者这些进程如何交替执行,并且在主调用代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个就程这个类是线程安全的

  • 原子性

    • AtomicXXX CAS 实现类 Unsafe.compareAndSwapInt
    • AtomicAdder 对AtomicLong 的优化 64 需要拆成两个32 位处理
    • AtomicRerference 实现了compareAndSet方法
    • AtomicIntegerFiledUpdater 要更新的字段必须要volatile标记,非static
    • AtomicStampReference CAS的ABA问题 ,增加了一个数据版本号
      • synchronized: 依赖JVM
        • 修饰代码块 作用于调用的对象
        • 修饰方法 作用于调用的对象
        • 修饰静态方法 作用于所有对象
        • 修饰类 作用于所有对象
      • Lock:依赖特殊的CPU指令,代码实现,ReentrantLock
    • 原子性对比
      • synchronized : 不可中断,适合竞争不激烈,可读性好
      • Lock 可中断锁,多样化同步,竞争激烈时能维持常态
      • Atomic:竞争激烈时能维持常态,比lock性能好,只能同步一个值
  • 可见性

    • 导致共享变量在线程 间不可见的原因
      • 线程交叉执行
      • 重排序结合线程交叉执行
      • 共享变量更新后的值没有在工作内存与主内存间及时更新
    • JMM(Java内存模型) 关于synchronized的两条规定
      • 线程解锁前,必须把共享变量的最新值刷新到主内存
      • 线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(加锁与解锁是同一把锁)
    • volatile 通过屏障和禁止重排序优化来实现, 并不是原子操作,不能实现线程安全
      • 对volatile变量写操作时,会在写操作后面加入一条store屏障质量,将本地内存中的共享变量值刷新到主内存
      • 对volatile变量读操作时, 毁在在读操作前加入一条load屏障指令,从主内存中读取共享变量
  • 有序性

    • Java 内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响大单线程程序的执行,却会影响到多线程并发执行的正确性
    • volatile ,synchronize,lock
    • happens-before 原则,如果两操作次序不能从happens-before推导出来就不能保证他们有序性,cpu可以对他们任意排序
      • 程序次序规则: 一个线程内,按照代码顺序,书写在前面的操作先行发生于与书写在后面的操作
      • 锁定规则:一个unlock操作先行发生于后面对同一个锁的lock 操作
      • volatile变量规则:对一个变量的写操作 先行发生于后面对这个变量的操作
      • 传递规则: 如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于 操作C

      • 线程启动原则: Thread对象的start()方法先行发生于此线程的每一个动作
      • 线程中断原则:对线程interrupt()方法的调用先行发生于比中断线程检测到中断事件的发生
      • 线程终结规则:线程中所有的操作都先发生于线程的终止检查,我们可以通过Thread.join()方法结束.Thread.isAlive()的返回值手段检测到线程已经终止执行
      • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

安全发布对象

  • 发布对象:使一个对象能够被当前范围之外的代码所使用
  • 对象逸出:一种错错误的发布,当一个对象还没有构造完成时,就使它被其他线程所见
  • 安全发布对象
    • 在静态初始化函数中初始化一个对象引用

      • 饿汉模式在类加载的时候初始化缺点
        • 私有构造函数逻辑过多会影响加载速度
        • 如果实例化的类没有被使用会浪费
      • 懒汉模式, sync也,双重检测会被cpu指令重排也是不安全的,需要使用volatile+双重检测
    • 净对象的引用保存到volatile类型域或者AtomicReference对象中

    • 将对象的引用保存到某个正确构造对象的final类型 域中

    • 净对象的引用保存到一个由锁保护的域中

    • 单例方法

      • 饿汉模式静态
      • 懒汉 volatile +代码同步+双重检测
      • 枚举
      • final不可变
  • 不可变对象
    • final
    • 引用不可变 Collections.unmodifiableMap()
    • 线程封闭
      • 什么是线程封闭?就是把对象封装到一个线程里,只有这个线程能够访问
      • ad-hoc 线封闭: 程序控制实现,最糟糕回来
      • 堆栈封闭: 局部变量,无并发问题
      • ThreadLocal 线程封闭,特别好的封闭方法, 要是记得释放资源,否则会内存泄露
        • 内部是一个map
        • key是当前线程名称,value就是要封闭的对象
    • 常见线程不安全
      • stringBuilder 不安全 stringbuffer 安全
      • SimpleDateFormat 不安全 DateTimeFormatter 线程安全,第三方joda-time
      • ArrayList HashSet HashMap 等Collects
      • 先检查后执行: if(condition(a)){ handle(a)}
    • 同步容器
      • ArraList -> Vector,Stack
      • HashMap -> HashTable (key,value都不能为null)
      • Collections.synchronizedXX(List,Set,Map)

J.U.C ,java util concurrent

  • 并发容器

    • ArrayList -> CopyOnWriteArrayList
    • HashSet, TreeSet -> CopyOnWriteArraySet ConcurrentSkipList支持自然排序
    • HasMap,TreeMap -> ConcurrentHashMap ,ConcurrentSkipListMap
  • 安全共享策略

    • 线程限制:一个被线程限制的对象,有线程独占,并且只能被占有他的线程修改
    • 共享只读:一个贡献只读的对象,在没有额外同步的情况下,可以被多个线程并发访问,但是任何一个线程都不能修改它
    • 线程安对象:一个线程安全的对象或者容器,在内部通过同步机制来保证线程安全,所以其他线程无需额外的同步就可以通过公共接口随意访问
    • 被守护对象:被守护对象只能通过获得特定的锁来访问

JUC AQS

  • AQS AbstractQueuedSynchronizer
    • 使用node实现了FIFO队列
    • 利用一个int类型表示状态
    • 使用方法是集成
    • 子类通过继承并通过他的方法管理状态 (acquier 和relese) 方法操纵状态
    • 可以同时实现排它锁和共享锁模式(独占,共享)
  • AQS 同步组件
    • CountDownLatch 线程计数

      • image.png
    • Semaphore 信号量 可以控制并发数量

    ```
          final Semaphore semaphore = new Semaphore(20);
          
          ///线程
          semaphore.acquire(); // 获取一个许可
          semaphore.acquire(n); // 获取多个许可
          //操作
          semaphore.release(); // 释放一个许可
          semaphore.release(3); // 释放多个许可
          
          
          
          semaphore.tryAcquire() //尝试获取一个许可,如果获取不到就丢弃
          semaphore.tryAcquire(1,TimeUnit.SECONDS) //尝试获取一个许可,等1s,如果获取不到就丢弃
      ```
    
    • CyclicBarrier 多个线程计数
      • image.png
      • 可以重置计数器
      • 达到条件后多个线程可以同步执行
    • ReentrantLock(可重入锁)与synchronize区别
      • 可重入性 ,基于计数器实现
      • r JDK实现,s JVM实现
      • jdk优化之前 r好,优化之后差不多基于CAS实现
      • 功能区别 r需要手动开关,jvm 自动
      • ReentrantLock 独有的功能
        • 可以指定公平锁,默认非公平锁
        • 提供了Condition ,可以分组唤醒
        • 提供能改改中断等待做的机制,locklocInterruptibly();
      • ReentrantReadWriteLock
      • StampedLock
    • Condition
    • FutureTask
      • callable 与runnable
        • callable 可以有返回,使用Future接收, futer.get();
      • Future 接口
      • FutureTask
    • Fork/Join 窃取算法 ,双端队列
      • image.png
    • BlockingQueue
      • 常见实现
        • ArrayBlockingQueue
        • DelayQueue
        • LinkedBlockingQueue
        • PriorityBlockingQueue 必须是compar接口
        • SynchronousQueue 只能存放一个
      • 生产消费场景
      • image.png
      • 四套方法
        image.png

线程池

  • new Thread() 弊端

    • 每次new Thrand 性能差,
    • 缺乏统一管理,可以无限制新建线程,占用过度系统资源
    • 确少更多功能,例如多执行,定期执行,线程中断
  • 线程池好处

    • 重用存在的线程,减少对象的创建消亡的开销
    • 可以有效控制最大并发数,提高系统资源利用率,可以避免过多资源竞争,避免阻塞
    • 提供定时,定期,单线程,并发数控制
  • ThreadPoolExecutor

    • corePoolSize 核心线程数量
    • maximuumPoolSize 线程最大线程数
    • workQueue 阻塞队列
    • keepAliveTime
    • unit 时间单位
    • threadFactory 线程工厂
    • rejectHandler 拒绝 策略
      • 丢弃
      • 使用当前调用者线程执行
      • 丢弃old
      • 丢弃当前
  • 线程池状态

    • image.png
  • 基础方法

    • execute() : 提交任务,交给线程池执行
    • submi(): 提交任务,能够返回执行结果 execute() +Future
    • shutdown(): 关闭线程池,等待任务执行完
    • shutdownNow(): 关闭线程池不等待任务执行完成
  • 监控方法

    • getTaskCount();
    • getCompletedTaskCount();
    • getPoolSize()
    • getActiveCount();
  • image.png
  • Executor 框架接口
    • Executors.newCachedThreadPool();
    • Executors.newFixedThreadPool();
    • Executors.newScheduledThreadPool();
    • Executors.newSingleThradExecutor();
  • 线程池配置
    • cpu密集型任务,就需要进来压榨CPU,参考值可以设置为NCPU+1
    • IO密集型任务,参考值可以设置为2*NCPU

J.U.C 学习总结

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容