高并发编程底层原理详解(1)

CAS (compare and swap)比较并交换

在不加锁的情况,保持在多线程的一致性问题? => CAS
1.知识铺垫:i++在jvm 中是不安全的,不能保证原子性,在高并发的情况下,会存在问题。JMM(每个线程都会把主内存的数据copy的线程自己的空间中,执行完毕之后再写回主内存。)
2.解决方式 a.加锁 b.CAS
3.案列:AtomicInteger getAndAddIn()
4.流程解析:
i = 0
Thread A i++ ( 拿到i=0 ,并i = i+1 ,准备存入)还未存入
Thread B 在Thread A拿到I=0 之后,先存入到主内存中, 此时 主内存中的值 已经变为1
Thread A 此时发现主内存已经变为1了,于是,拿到i=1 ,重新执行 i = i+1 ,并写入到主内存中。(假设仅仅有2个线程。)
5.引发新问题 ABA 问题:
概念:线程a在最终写入主内存时,仅仅会比较当前值,而不关注他的变化过程(他可能由 0—>1>0)
解决方案:加一个版本号,乐观锁

   //如果不相等的话,则继续执行一遍,再拿出值,进行比较,直到相等 则写入。
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2); //native 实现。
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//native 实现。

        return var5;
    }
//引出汇编指令(也就是说硬件直接支持)如果为多个cpu则加个lock
lock cmpxchg    => compare  exchange(lock保证原子性,其他cpu无法访问)
volatile 和syn  都是通过它实现
image.png

java在内存中的存储布局

1.Object o = new Object()在内存中占用多少个字节? => 16个字节(内容为空,比如说:int 4个字节,对象引用4个字节)
2.对象头 markword 8个字节(锁信息、分带年龄)(=>可以回顾一下垃圾回收过程:CMS 6 JVM 15 默认)
-- a.new -> 偏向锁-> 轻量级锁(无锁、自旋锁、自适应锁)->重量级锁 (syn的优化过程)
3.class 对象指针,指向class对象(默认开启压缩,被压缩 成4个字节,原8个)
4.实例数据:对象中存的数据、int 4个字节,string 4个字节(压缩后)
5.对齐(若不为8的倍数,则自动补齐,优化方式,8字节更快)

//依赖
<dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.10</version>
</dependency>

//测试代码
  public static void main(String[] args) {
        Object obj = new Object();
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
    }
image.png
image.png

Syn的优化过程

前置知识:由用户态 向 内核态申请重量锁 ,非常耗费资源。
1.无锁
2.偏向锁(存放线程指针、 偏向锁标记为1):线程执行任务是很快的,一般也不会冲突,因此,默认只需要加一个标记,而不需要上锁
3.轻量级锁(自旋锁,也就无锁):释放偏向锁,记录Lock Record (CAS )缺点:耗费CPU,适用于竞争不太激烈的情况
4.重量级锁,指向重量级锁(mutex 互斥量)的指针,锁标记为10,当竞争加剧、或者自旋超过 n次,则升级,每一个重量级锁都有一个队列,没被执行的任务、是不会占用cpu的
5.GC标记信息:CMS过程用到的标记信息 锁状态为11
6:上锁时,hashCode 会被 存放到LR中。

锁降级、锁消除和锁粗化

1.锁降级 -> GC的时候会发生
2.锁消除,如果JVM发现某个局部变量、并不会被其他线程调用,则会把syn取消
3.锁粗化,如果一直循环的在加锁、释放锁,JVM会优化成只在while中加一次锁。

Syn的最底层实现

linux +HSDIS 做测试
HSDIS 反汇编工具 HotSpot Di assembly
·JIT Just In Time 及时编译器 ,将热点代码直接编译成机器语言,而不在重新编译了。
最终会发现加了syn 或者使用了volatile变量 的方法 底层都是 lock cmpexh

Syn的实现过程

1.java代码:synchronized 关键字
2.字节码 monitorenter moniterexit
3.jvm 在执行过程中自动升级
4.硬件级 汇编语言 comxchg (compare and exchange)

Volatile

前置知识:
计算机组成原理: 核心就是CPU+内存+外设(硬盘、显示器、网卡等等。)
执行过程:内存中存放的就是指令,CPU获取、并执行指令。
PC寄存器 是存放下一条指令的位置

ALU:计算
cache:多级缓存( 金字塔结构 容量大、速度慢。 寄存器最快、硬盘最慢 (1:100w))
cache:就是缓存 用来提升访问速度的。
进程和线程的区别:线程是CPU执行的基本单位。进程是CPU分配资源的基本单位。
线程切换:Context Switch 当2线程进行切换时,需要将正在执行的线程的数据进行保存。再执行第二个线程。
超线程:一个ALU对应2组PC|Registers ,每个线程对应一组 PC|Registers ,因此 多线程进行切换时,并不需要保存当前线程的的数据。这就是所谓的四核八线程,因此线程切换的速度更快了。
缓存行 cache line:按行读取(获取变量时,会把相邻数据一同获取过来,最近优先原则)一行数据是64个字节。
缓存行越大,局部效率越高、但读取时间慢、
缓存行越小、局部性效率低、但读取时间快、(目前最优选择64字节)
MESI (E(exclusive)、M(modified)、S(shared)、I(invalid))缓存一致性协议、不同的CPU用的协议都是不一样的。(省略详细过程)

基础作用:
保证线程间的可见性。(每个线程都有自己的内存空间,获取变量时,会复制一份到内存中,当主内存中的值变化时,会同步到各个线程中。)

禁止指令重排:
概念:CPU的乱序执行,比如说 step1 需要耗费100ms step2 需要10ms。则step2可能与step1并行。则step2先执行完毕。(测试案列:略)
实现方式如下:
JVM:内存屏障
汇编:lock指令

源自马士兵2020年最新Java多线程高并发编程详细讲解公开课:
https://www.bilibili.com/video/BV1xK4y1C7aT?p=2

image.png

image.png

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

推荐阅读更多精彩内容