AQS和CAS的简单理解和部分锁理解

AQS

AQS的定义

AQS 是⼀个⽤来构建锁和同步器的框架,使⽤ AQS 能简单且⾼效地构造出应⽤⼴泛的⼤量的同
步器,⽐如我们提到的 ReentrantLock ,countdownlatch cyclicbarrier

AQS 核⼼思想

如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的⼯作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占⽤,那么就需要⼀套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是⽤ CLH 队列锁实现的,即将暂时获取不到锁的线程加⼊到队列中。

缺点

可能导致队列中的线程长时间获取不到锁,导致饿死

源码

aqs源码

在这里插入图片描述

CAS

什么是cas

CAS算法 即compare and swap(比较与交换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数

核心

当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试。 列入数据库乐观锁版本号问题来理解cas

缺点

CAS缺点
1.循环会耗时
2.一次性只能保证一个共享变量的原子性
3.引发ABA问题

源码

cas源码

CAS 查看笔记

入口

  AtomicInteger atomicInteger = new AtomicInteger();
   atomicInteger.compareAndSet()

在这里插入图片描述

直接操作内存

在这里插入图片描述

native 调用c++

=================================================================================

锁:

锁只会升级不会降级
先来了解对象头
每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针。不加 synchronized 的对象不会关联Monitor。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自旋锁

自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。

共享锁

共享锁是指该锁可被多个线程所持有。如果线程对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。

排它锁

一开始就理解有人来抢占资源 直接锁 从头执行到结束 释放

公平锁和非公平锁

公平锁 排队等待拿资源 多出了唤醒操作 唤醒线程浪费 但是会出现内核切换产生负载问题
非公平锁 没有顺序来执行拿资源 出现线程等待饿死在队列中的存在 双向链表

读锁和写锁

读锁:读操作时,可以允许多个线程同时获得读操作。但是同一时刻只能有一个线程可以获得写锁。其它获取写锁失败的线程都会进入睡眠状态,直到写锁释放时被唤醒。
写锁:写锁会阻塞其它读写锁。当有一个线程获得写锁在写时,读锁也不能被其它线程获取;写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)。适用于读取数据的频率远远大于写数据的频率的场合。

死锁

所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。
产生死锁的四个必要条件
1) 互斥条件:一个资源每次只能被一个进程使用。
2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3) 不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

打破任意条件死锁就不成立

可重入锁

又名递归锁(拿到大门的锁,就可以拿到房间的锁)

偏向锁

它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步
很多情况下,一个锁对象并不会发生被多个线程访问得情况,更多是被同一个线程进行访问,如果一个锁对象每次都被同一个线程访问,根本没有发生并发,但是每次都进行加锁,那岂不是非常耗费性能。所以偏向锁就被设计出来了。

偏向,也可以理解为偏心。当锁对象第一次被某个线程访问时,它会在其对象头的markOop中记录该线程ID,那么下次该线程再次访问它时,就不需要进行加锁了。但是这中间只要发生了其他线程访问该锁对象的情况,证明这个对象会发生并发,就不能对这个对象再使用偏向锁了,会进行锁的升级
在这里插入图片描述

轻量级锁

自旋 获取轻量锁的过程与偏向锁不同,竞争锁的线程首先需要拷贝对象头中的Mark Word到帧栈的锁记录中。拷贝成功后使用CAS操作尝试将对象的Mark Word更新为指向当前线程的指针。如果这个更新动作成功了,那么这个线程就拥有了该对象的锁。如果更新失败,那么意味着有多个线程在竞争。
当竞争线程尝试占用轻量级锁失败多次之后(使用自旋)轻量级锁就会膨胀为重量级锁,重量级线程指针指向竞争线程,竞争线程也会阻塞,等待轻量级线程释放锁后唤醒他。

这里是引用

重量级锁

阻塞 重量级锁在JVM中有一个监视器(Monitor),保持了两个队列:锁竞争队列和信号阻塞队列,一个实现线程互斥,另一个实现线程同步。重量级锁在底层是靠操作系统的Mutex Lock实现的,线程在阻塞和唤醒状态间切换需要操作系统将线程在用户态与核心态之间转换,成本很高,所以最早的synchronized效率不高。

偏向锁、轻量级锁和重量级锁对比

在这里插入图片描述

synchronized底层原理

底层

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
资源内容 基本概念:介绍并发编程的基本概念,如进程、线程、并行与并发的区别等。 同步机制:讲解如何使用、信号量、原子操作等同步机制来避免竞态条件和死。 并发模型:介绍不同的并发模型,如生产者-消费者模型、管道模型、消息传递模型等。 并发工具:介绍并发编程中使用的工具和库,如线程池、并发集合等。 性能优化:讨论如何优化并发程序的性能,包括减少上下文切换、提高缓存效率等。 错误处理:讲解并发编程中的错误处理,如异常安全、错误传播等。 实际案例:通过实际的编程案例来展示并发编程的应用。 适合的人群 初学者:对计算机科学或编程有一定了解,但尚未接触过并发编程的开发者。 中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统感兴趣的学生。 系统架构师:负责设计和优化大型系统架构,需要了解并发编程以提高系统性能的专业人员。 学习资源 在线课程:如Coursera、edX、Udemy等平台上的并发编程课程。 书籍:如《Java并发编程实战》、《Concurrency in C++》等。 官方文档:不同编程语言的官方文档通常会提供关于并发编程的指南和最佳实践。 社区和论坛:如Stack Overflow、Reddit等,可以提供实际问题的帮助和讨论。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张航柯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值