并发编程篇

简介: 并发编程篇

一:乐观锁CAS和自旋锁的关系

自旋锁是基于CAS实现的。

CAS没有自旋或者重试的效果,但是自旋锁是基于类似do-while的形式,不断尝试,直到成功为止。

CAS本质就是Unsafe类中的一个方法,他只会尝试一次,成功返回true,失败返回false。

CAS并不是在Java端实现的一个功能,而是在C++里面做的。

最终CAS会被翻译成一个指令。Atomic::cmpxchg,而这个指令是CPU原语,CPU认识这个指令。

二:CAS的效果是什么,在Java中如何使用CAS

CAS就是比较和交换,就是将内存中的某一个值,从oldValue,替换为newValue。替换的过程是先用oldValue比较内存值,如果一致,就替换,然后返回true。如果比较不一致,返回false。

比较和交换这两个操作是一条指令实现的。

Java中想用CAS操作的话,无法直接通过new或者是他提供的静态方法,直接使用。会抛出java.lang.SecurityException: Unsafe异常。

想用的话,unsafe类的对象需要通过反射的方式拿到。

public class MyTestCAS {
 
    private int value = 1;
 
    public static void main(String[] args) throws Exception {
        MyTestCAS test = new MyTestCAS();
        Unsafe unsafe = null;
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        unsafe = (Unsafe) field.get(null);
        // 获取内存偏移量
        long offset = unsafe.objectFieldOffset(MyTest.class.getDeclaredField("value"));
        // 执行CAS,这里的四个参数分别代表什么,你也要清楚~
        System.out.println(unsafe.compareAndSwapInt(test, offset, 0, 11));
        System.out.println(test.value);
    }
 
}

三:CAS常见问题,以及如何解决

ABA问题:不一定是问题,大多数情况下,只存在++,--这种操作时,无所谓你这个值是否被改过。对最终结果和业务没影响的,不需要考虑。

如果要求整个过程的变化不存在并发问题,不能出现ABA的情况,就必须追加类似版本号的效果,Java中也提供了AtmoicStampedReference

自旋次数过多:

  • 自旋一定次数,就挂起线程,别CAS了,浪费CPU资源。
  • 采用分段锁的形式,不要专注于一个属性,如果业务允许,可以分开计算,最终汇总。

CAS本质无法锁住一段代码,只能保证修改一个属性的原子性:But,ReentrantLock就是基于CAS的原子性类实现锁住一段代码的。

四:synchronized的锁升级过程

无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁?是这么一步一步走过来的么?

其实状态不是这样一点一点来的。

无锁无法到偏向锁  

偏向锁是可以到无锁状态的,偏向锁没有地儿存储hashcode之类的值,为了存储,要么升级到轻量级锁,存储到LockRecord里,要么降级为无锁,存在MarkWord里。

五:AQS是什么

先说清楚和JUC的关系以及说和JUC下其他类的关系,然后说内部的核心结构。你可以往你会的地方拐。

AQS本质就是JUC包下的一个抽象类,JUC包下的一些并发工具,并发集合,线程池,锁都是基于AQS作为基础类去实现的。

AQS里面有一个核心属性和两个核心的结构:

  • volatile修改是,并且基于CAS修改的state属性。
  • 由Node组成的一个双向链表,或者说叫同步队列。
  • 由Node组成的一个单向链表,这个是用于实现类似synchronized的wait和notify的结构。

六:ReentrantLock获取锁的方式

  • lock
  • tryLock()
  • tryLock(time,unit)
  • lockInterruptibly

lock方法:死等,如果那不到锁,就一直等,你interrupt中断了也一直等。

tryLock()方法:浅尝一下,试一下,就一下,拿到快乐的返回true,拿不到,返回false。

tryLock(time,unit)方法:尝试time.unit这么尝试时间,如果拿到了,返回true,时间到了,没拿到,返回false。如果在拿的过程中,线程中断了,就抛出异常。

lockInterruptibly方法:死等,如果那不到锁,就一直等,如果被interrupt中断了,抛出异常

七:AQS中node的几种状态

Node有5种状态,1,0,-1,-2,-3

  • 1:代表当前Node已经取消了,不排队了。
  • 0:代表代表默认状态,啥事没有~
  • -1:代表当前节点的next Node挂起了,需要被唤醒
  • -2:当前Node被await挂起了,扔到了Condition的单向链表里。
  • -3:传播用的,共享资源里会用到,读线程拿到锁资源后,如果同步队列里排的是共享资源Node,那就继续唤醒。

八:AQS中取消结点的过程

想拿资源的线程在排队,但是不想排了,需要取消排队的Node。

1、将排队的Node里的线程设置为null

2、跳过取消的前继节点,找到有效节点连接上

3、将Node的状态设置为1,代表取消

4、后续节点操作,分为几种情况

  • 取消的节点是tail:直接更换尾节点为有效的前继节点
  • 取消的节点不是head.next:确保后继节点可以被唤醒,将前继节点设置为-1。
  • 取消的节点是head.next:直接唤醒后继节点。

5、将取消的节点的next指向自己

九:AQS中被唤醒时,head.next有问题时,怎么找

是从队列从后往前找,因为如果next后取消的节点,取消节点会将next指向自己,直接找不到了。

另外,节点加入的顺序,是先连接prev,再连接tail,最后将前继节点的next指向自己。

在AQS里,prev指针始终是正确的,next说不定。

十:为什么会有ReentrantReadWriteLock

首先,读写锁能解决的,互斥锁肯定能解决,但是,互斥锁的效率可能比较低。

比如说有一个业务,平均下来,10次读操作,1次写操作。

如果用互斥锁,可以保证线程安全,但是10次读操作也需要一个一个来。

但是,读读操作没有线程安全问题。

但是只要涉及到了写操作,比如读写操作,需要保证线程安全。只要有写线程,就必须满足互斥性。

所以JUC下就提供了一个ReentrantReadWriteLock,读写锁。这个锁的特点,就是读读可以一起操作,但是只要涉及到了写操作,就必须保证互斥。

十一:ReentrantReadWriteLock 是如何基于AQS实现的

lock锁,无论是读锁还是写锁,都是基于state属性判断的。

state是int,占32个bit为,将高16为,作为读锁的标识,低16位,作为写锁的标识。

如果线程要拿读锁,只需要确认没有写线程在持有写锁资源,并且队列中的head.next不是写锁(解决写锁饥饿问题),就可以直接获取读锁资源。

写锁需要确保没有读线程在持有读锁,并且没有其他线程在持有写锁,写锁才能拿到锁资源。

相关文章
|
1天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1506 1
|
28天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
4天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
453 17
|
1天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
176 0
|
7天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
20天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
8天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
392 3
|
6天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
300 2
|
22天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
24天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2603 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析