• JMM内存模型


    一、

    上下文切换问题:时间片一般是几十毫秒,任务从保存到再加载的过程就是一次上下文切换,多线程竞争锁时会引起上下文切换,时间片到了会引起上下文切换

    减少上下文切换:1、无锁并发线程  2、CAS算法  3、使用最少线程  4、协程

    死锁问题:1、尽量避免一个线程同时获得多个锁

         2、尽量避免一个线程在锁内同时占用多个资源  

         3、尝试使用定时锁lock.tryLock(timeout)

         4、对于数据库锁,加锁和解锁必须在同一个数据库连接里

    二、JVM的并发机制

    1、volatile关键字:

    volatile比synchronized执行成本更低,因为他不会引起线程上下文的切换和调度

    被volatile修饰的共享变量进行写操作的时候会多出一条以lock为前缀的汇编指令:1、lock指令会引起会引起处理器缓冲回写到内存  2、一个处理器的缓冲回写到内存会引起其它处理器的缓冲失效

    volatile关键字的作用:1、保证可见性  2、禁止指令重排序【但这两个功能的底层实现都是lock指令】

    2、synchronized关键字(抛出异常自动释放锁)

    所以synchronized的底层操作含义是先对对象头的锁标志位用lock cmpxchg的方式设置成“锁住“状态,释放锁时,在用lock cmpxchg的方式修改对象头的锁标志位为”释放“状态,写操作都立刻写回主内存

    无所状态---->偏向锁状态---->撤销偏向锁状态---->轻量级锁状态---->重量级锁状态

    偏向锁的撤销是狠耗时的

    偏向锁通过偏向锁的撤销膨胀成轻量级锁·

    轻量级锁通过自旋膨胀成重量级锁

    3、原子操作的实现原理:(CAS操作同时具有volatile读-写的语义)

      (1)、总线锁

      (2)、缓冲锁(并不是都支持)

      (3)、CAS就是利用lock CMPXCHG指令实现的(JAVA所用)

        ①ABA问题

        ②循环时间长开销大

        ③只能保证一个共享变量的原子操作

        ④JVM的synchronized的机制中也用了CAS的锁机制

    三、JVM的内存模型

    线程之间的通信方式:共享内存(JAVA所用)和消息传递

    堆内存是所有线程共享的

    缓冲区和重排序这两个问题

    重排序:编译器重排序、指令集并行重排序、内存系统重排序【JMM会限制编译器重排序,也会通过插入内存屏障的指令的方式来禁止一些处理器重排序】

    由于处理器使用了写缓冲区,所以会对storeload操作进行重排序【这个屏障会把当前所有写缓冲区的数据全部刷新到内存中】

    as-if-serial[同一线程内的数据依赖性]

    happen-before[多线程之间存在可见性,那么就一定存在happen-before规则]

    顺序一致性模型

    synchronized及临界区内的代码是可以重排序的

    1、volatile语义:

      严格限制volatile变量和普通变量的重排序

      volatile的单个变量的读写操作具有原子性

      对一个volatile变量的读,总是能看到之前最后一次对这个变量的写

      volatile的写和锁的释放具有相同的内存语义

      volatile的读和锁的获取具有相同的内存语义

      当写一个volatile变量时,JMM会把该线程对应的本地内存中的所有写的共享变量值刷新到主存中

      当读一个volatile变量时,JMM会把该线程对应的本地内存值为无效。线程接下来将从主内从中读取所有读的共享变量

      内存语义的实现:1、storestore  volatile写  storeload  2、volatile读  loadload loadstore

      用途:一写多读

    2、锁的内存语义:

      临界区互斥执行

      当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中

      当线程获取锁时,JMM会把该线程对应的本地内存值为无效,从主内从中刷新共享变量

      内存语义的实现:

      CAS(compareAndSwap())同时具有volatile的写和读的内存语义

    3、final的内存语义:

      (1)在构造函数中对final域的写入和把这个堆对象赋值给它的引用,他们之间不能重排序

      (2)初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能进行重排序

    垃圾回收器:

      1、垃圾回收线程是怎么让其他用户线程到安全点都自动停止下来的?

        主动式中断:不对线程操作,仅仅设置中断标志;每个线程执行时主动轮询这个标志,发现中断标志为真时,就自己中断挂起;轮询标志的地方和安全点是重合的。

      2、垃圾回收线程是怎么让其他用户线程到安全区域都自动停止下来的?

        当位于安全区域的线程在线程离开安全区域时,会检测系统是否已经完成了根节点的枚举,如果没有完成,则必须等待收到离开区域的信号为止。

  • 相关阅读:
    github
    保存中文文本
    python3与 python2 urllib模块区别
    gitbook 使用粘自csdn
    html基础
    R语言学习笔记之十
    R语言学习笔记之九
    R语言学习笔记之八
    R语言学习笔记之七
    R语言学习笔记之六
  • 原文地址:https://www.cnblogs.com/erdanyang/p/12346767.html
Copyright © 2020-2023  润新知