返回顶部
首页 > 资讯 > 后端开发 > Python >带你快速搞定java多线程(4)
  • 842
分享到

带你快速搞定java多线程(4)

2024-04-02 19:04:59 842人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录1、AQS 是什么?2、AQS 模型3、AQS state4、AQS 两种资源共享方式:5、模板方式实现自定义6、锁的分类:公平锁和非公平锁,乐观锁和悲观锁7、CAS8、总结1、

1、AQS 是什么?

AQS 是类 AbstractQueuedSynchronizer的简称,也是常用锁的基类,比如常见的ReentrantLock,Semaphore,CountDownLatch 等等。

AQS提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架。是Java提供的一种模板,一般在现有同步器无法完成的时候可以自行扩展。当然也可以自己实现,不过既然有现成的为什么还要自己瞎鸡儿写。

图片

2、AQS 模型

图片

注意:图来自网上,具体的原地点在哪我也不知道。如果有问题可以联系我。

解释:整个模型相当于在食堂吃饭,只开了一个窗口,只有一个打饭的师傅(state),所有想要吃饭的线程必须排队等待,直到轮到自己。

AQS就是基于队列,用共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。代码解决现实问题,现实问题催生解决方案。

3、AQS state

state 代表 共享资源和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。

state的访问方式有三种:

  • getState()
  • setState()
  • compareAndSetState()

4、AQS 两种资源共享方式:

1.Exclusive:独占,只有一个线程能执行,如ReentrantLock

2.Share:共享,多个线程可以同时执行,如Semaphore、CountDownLatch、ReadWriteLock,CyclicBarrier。

5、模板方式实现自定义

不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。自定义时主要实现以下几种方法:

  • isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
  • tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
  • tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
  • tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
  • tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

以ReentrantLock为例,state初始化为0,表示未锁定状态。A线程lock()时,会调用tryAcquire()独占该锁并将state+1。此后,其他线程再tryAcquire()时就会失败,直到A线程unlock()到state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A线程自己是可以重复获取此锁的(state会累加),这就是可重入的概念。但要注意,获取多少次就要释放多么次,这样才能保证state是能回到零态的。

再以CountDownLatch以例,任务分为N个子线程去执行,state也初始化为N(注意N要与线程个数一致)。这N个子线程是并行执行的,每个子线程执行完后countDown()一次,state会CAS减1。等到所有子线程都执行完后(即state=0),会unpark()主调用线程,然后主调用线程就会从await()函数返回,继续后余动作。

一般来说,自定义同步器要么是独占方法,要么是共享方式,他们也只需实现tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared中的一种即可。但AQS也支持自定义同步器同时实现独占和共享两种方式,如ReentrantReadWriteLock。

6、锁的分类:公平锁和非公平锁,乐观锁和悲观锁

  • 公平锁:当线程A获取访问该对象,获取到锁后,此时内部存在一个计数器num+1,其他线程想访问该对象,就会进行排队等待(等待队列最前一个线程处于待唤醒状态),直到线程A释放锁(num = 0),此时会唤醒处于待唤醒状态的线程进行获取锁的操作,一直循环。如果线程A再次尝试获取该对象锁时,会检查该对象锁释放已经被占用,如果还是当前线程占用锁,则直接获得锁,不用进入排队。
  • 非公平锁:当线程A在释放锁后,等待对象的线程会进行资源竞争,竞争成功的线程将获取该锁,其他线程继续睡眠。

公平锁是严格的以FIFO的方式进行锁的竞争,但是非公平锁是无序的锁竞争,刚释放锁的线程很大程度上能比较快的获取到锁,队列中的线程只能等待,所以非公平锁可能会有“饥饿”的问题。但是重复的锁获取能减小线程之间的切换,而公平锁则是严格的线程切换,这样对操作系统的影响是比较大的,所以非公平锁的吞吐量是大于公平锁的,这也是为什么jdk将非公平锁作为默认的实现。

  • 悲观锁:总是假设最坏的情况,每次想要使用数据的时候就恰好别人也要修改数据,一切是以安全第一,所以在每次操作资源的时候都会先加锁,不管有没有人抢,然后独占资源。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现
  • 乐观锁:乐观锁和悲观锁刚好相反,自己使用资源的时候没有人抢,所以不需要上锁。乐观锁的实现方案一般来说有两种:版本号机制 和 CAS实现 。乐观锁多适用于多度的应用类型,这样可以提高吞吐量。

7、CAS

CAS(Compare And Swap),即比较并交换。是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。sun.misc.Unsafe 类提供了硬件级别的原子操作来实现这个CAS。java.util.concurrent 包下的大量类都使用了这个 Unsafe.java 类的CAS操作。Unsafe 包是c++的接口实现,直接可以访问计算机的内存等敏感操作,所以标记为Unsafe。

CAS 是直接调用计算机的硬件指令,是硬件级别的线程同步,也是一种乐观锁。

8、总结

从整体上说了下AQS,没有深入到代码层级,先理解思想,后看具体实现。你理解了吗?下期具体分析一个CountDownLatch 源码,从细节理解AQS。

本篇文章就到这里了,希望能对你有所帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: 带你快速搞定java多线程(4)

本文链接: https://lsjlt.com/news/130499.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 带你快速搞定java多线程(4)
    目录1、AQS 是什么?2、AQS 模型3、AQS state4、AQS 两种资源共享方式:5、模板方式实现自定义6、锁的分类:公平锁和非公平锁,乐观锁和悲观锁7、CAS8、总结1、...
    99+
    2024-04-02
  • 带你快速搞定java多线程
    目录1、什么是线程2、线程的状态3、怎么通俗理解进程,线程?4、线程和进程的区别5、什么是线程安全6、如何创建线程总结:1、什么是线程 线程是操作系统调度的最小单元,也叫轻量级进程。...
    99+
    2024-04-02
  • 带你快速搞定java多线程(2)
    目录1、Future的类图结构,从整体上看下Future的结构2、future的使用,说的再多都么什么用,来个例子悄悄怎么用的。3、通俗理解4、原理5、总结1、Future的类图结构...
    99+
    2024-04-02
  • 带你快速搞定java多线程(3)
    目录一、锁的概念二、synchronized 的使用方式三、synchronized 的实现原理列小结四、线程池是什么五、为什么要用线程池?六、看下类图,从整体上理解下七、线程池的创...
    99+
    2024-04-02
  • 带你快速搞定java多线程(5)
    目录1、介绍2、countdownlantch的用法。3、如何利用AQS 实现 CountDownLatch4、总结1、介绍 CountDownLantch 倒数计时器,一个同步辅助...
    99+
    2024-04-02
  • 带你快速搞定java IO
    目录一、IO底层是怎么回事?二、梳理类的结构三、IO类大点兵四、来波实例展示1、访问操作文件(FileInputStream/FileReader ,FileOutputStream...
    99+
    2024-04-02
  • 带你快速搞定java数组
    目录1、数组的定义2、array 遍历3、List和array 之间的转换1、数组转list2、list 转数组3、Arrays工具类4、可能遇到的问题总结1、数组的定义 ...
    99+
    2024-04-02
  • 带你快速搞定java并发库
    目录一、总览二、Executor总览三、继承结构四、怎么保证只有一个线程五、怎么保证时间可以定时执行六、使用总结一、总览 计算机程序 = 数据 + 算法。 并发编程的一切根本原因是为...
    99+
    2024-04-02
  • 带你快速搞定Mysql优化
    目录1、查询语句的执行顺序2、数据类型的选择3、索引优化主键索引多列索引4、查询性能优化1、查询的生命周期2、SELECT语句尽量指明查询字段名称3、小表驱动大表总结1、查询...
    99+
    2024-04-02
  • 一篇文章带你搞定Python多进程
    目录1.Python多进程模块2.Python多进程实现方法一3.Python多进程实现方法二4.Python多线程的通信5.进程池1.Python多进程模块 Python中的多进程...
    99+
    2024-04-02
  • 一篇文章带你搞定JAVA Maven
    目录1、maven是什么,为什么存在?项目结构是什么样子,怎么定位jar2、Idea 的操作1.新建maven项目2.配置仓库3.添加依赖,添加fastjson的依赖4.打包项目3、...
    99+
    2024-04-02
  • 怎么快速了解Java多线程
    这篇文章主要讲解了“怎么快速了解Java多线程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么快速了解Java多线程”吧!线程线程的概念:线程(英语:Thread)是操作系统能够进行运算调...
    99+
    2023-06-16
  • 一篇文章带你搞定JAVA泛型
    目录1、泛型的概念2、泛型的使用3、泛型原理,泛型擦除3.1 IDEA 查看字节码3.2 泛型擦除原理4、?和 T 的区别5、super extends6、注意点1、静态方法无法访问...
    99+
    2024-04-02
  • 一篇文章带你搞定JAVA注解
    目录1、注解是什么2、jdk支持的注解有哪些2.1 三种常用的注解:2.2 元注解3、注解实例1、自定义注解2、在对应的方法上增加注解3、在项目启动的时候检查注解的枚举4、总结1、注...
    99+
    2024-04-02
  • 一篇文章带你搞定JAVA反射
    目录1、反射的概念1、概念2、获取字节码文件对象的方式2.1 元数据的概念2.2 获取class对象的方式1、访问权限2、获取方法2.1 访问静态方法2.2 访问类方法 3...
    99+
    2024-04-02
  • 一文带你搞懂Java中线程的创建方式
    目录一. 继承Thread二. 创建Runnable对象三. 创建Callable对象四. 基于Runnable创建FutureTask总结一. 继承Thread 可以通过创建Thr...
    99+
    2023-03-06
    Java线程创建方式 Java线程创建 Java线程
  • 一篇搞懂Java多线程
    Java多线程是指在一个程序中可以同时执行多个线程,每个线程执行不同的任务。多线程可以提高程序的并发性和效率。Java多线程的实现有...
    99+
    2023-09-14
    Java
  • 一篇文章带你搞懂Java线程池实现原理
    目录1. 为什么要使用线程池2. 线程池的使用3. 线程池核心参数4. 线程池工作原理5. 线程池源码剖析5.1 线程池的属性5.2 线程池状态5.3 execute源码5.4 wo...
    99+
    2022-11-13
    Java线程池实现原理 Java线程池原理 Java线程池实现 Java线程池
  • 手把手带你用java搞定汉诺塔
    目录什么是汉诺塔问题剖析n=1n=2n=3小结Java代码实现代码讲解move函数hanoiTower函数附:C语言实现汉诺塔总结什么是汉诺塔 汉诺塔问题是一个经典的问题。汉诺塔(H...
    99+
    2024-04-02
  • 一篇文章带你入门java多线程
    目录一、描述二、一个线程的生命周期三、线程的优先级四、创建线程五、示例1、Runnable接口2、继承Thread3、Callable 和 Future 创建线程4、测试总结一、描述...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作