尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

javaEE初阶————多线程进阶(1) - 教程

javaEE初阶————多线程进阶(1) - 教程
📅 发布时间:2026/6/20 18:48:20

javaEE初阶————多线程进阶(1) - 教程

今天我们开始学习多线程的进阶部分啦,这部分很像八股文,我们其实可能应用的很少,但是可能面试我们会被问到的,来学习吧;

1,常见锁策略

锁策略呢,并不是java独有的,如果需要我们自行去实现一个锁,我们就要遵循锁策略,但是synchronized和ReentrantLock实际上已经很够用了,技多不压身,下面正式开始介绍;

1)乐观锁和悲观锁

乐观锁和悲观锁呢,指的是当前锁具有乐观和悲观的特性,而不是说某一个特定的锁,他们都是加锁时候的场景,会判断锁的处境是乐观还是悲观的;

乐观:就是在加锁的时候,预测接下来的锁竞争并不激烈,不需要做额外的工作,不真正加锁,直接访问;

悲观:加锁的时候,预测接下来的锁竞争很激烈,需要做一些工作来解决,访问共享数据之前先加锁;

乐观锁的实现可以引入一个版本号,借助版本号来识别当前数据的版本号是否存在访问冲突;

悲观锁的实现就是先加锁(操作系统的mutex),获取到锁在真正的操作数据;

2)重量级锁和轻量级锁

轻量级锁和重量级锁就是遇到乐观场景和悲观场景的解决方案;

轻量级锁:在乐观的情况下,付出更高的代价,低效,大量内核态用户切换,很容易引发线程调度;

重量级锁:在悲观的情况下,付出更小的代价,高效,少量内核态用户切换,不容易引发线程调度;

大家还记得内核态和用户态我们在哪里讲过吗,没错(我才你答对了),就是线程池,我们之前说为啥要引出线程池呢,有一个原因就是,自己创建线程是需要到内核态去的,是不可控的,而使用线程池是在用户态,是我们可控的;

3)挂起等待锁和自旋锁

挂起等待锁呢就是重量级锁的典型实现,自旋锁就是轻量级锁的典型实现;

挂起等待锁:操作系统内核级别的,加锁的时候发现竞争,就会让线程进入阻塞状态,这个阻塞是不占用cpu的,后续的唤醒也需要内核来唤醒,即使当前的锁没有竞争了,我们也不会直接拿到它,会一直阻塞;

自旋锁:应用程序级别的,加锁的时候发现竞争,不会让线程进入阻塞状态,会一直占用cpu,会一直忙等;

4)普通互斥锁和读写锁

普通互斥锁就是锁的特性,一个线程占有了当前的锁,其他的锁就要阻塞等待并且不可剥夺;

读写锁呢就是读加锁和读加锁直接是不互斥的,读加锁和写加锁之间是互斥的,写加锁和写加锁之间也是互斥的,有同学可能会有疑问,加锁不是为了保证线程安全吗,读加锁和读加锁之间不互斥难道没有线程安全吗,读操作是原子的,不涉及到修改,所以是没有问题的;

读写锁是适用于特定场景下的,适用于读多写少的情况下,比如写小说,写操作只有作者一人,而读就有很多很多了,读加锁和写加锁操作互斥为了保证不读一个不完整的数据;

5)可重入锁和不可重入锁

我们之前讨论死锁的时候说过,一个线程一把锁怎么造成死锁,要获取锁的时候再次获取锁,让两个锁达成“2:我要锁,1:不行,你先上一边去,我要过去就能释放锁了,2:你先把锁给我我才能走开啊,1:我得先走开才能释放啊‘’,他俩就这样一直僵持着;

造成这种情况就因为这个锁具有不可重入的特性,而可重入锁就不会有这样的情况;

一个线程一把锁,可以连续多次加锁;

6)公平锁和非公平锁

公平锁就是先来后到,谁先来的,谁就获得当前的锁;

非公平锁就是概率均等,什么时候来,你获得锁的概率就是一样的;

可能感觉概率均等才是公平的,但是你把锁想像成打饭阿姨你就觉得公平锁真不错;

_____________________________________________________________________________

2,CAS

1,什么是CAS

CAS 即 compare and swap 比较和交换,CAS是CPU上的一条指令,它有三个参数,一个是内存地址,另两个都是寄存器的值,我们要表内存地址和寄存器1的值是否相等,如果相等就把寄存器2的值赋值给内存地址;

2,CAS有哪些应用
1)实现原子类

我们之前讲过,我们要保证原子性要去对某些操作加锁,但是我们刚才谈到CAS是原子的,我们就用它构造出了很多可以具有原子性的类,来代替基本的类型;

public class Demo1 {
public static void main(String[] args) throws InterruptedException {
AtomicInteger a = new AtomicInteger();
Thread thread = new Thread(()->{
for (int i = 0; i {
for (int i = 0; i < 10000; i++) {
a.incrementAndGet();
}
});
thread.start();
thread1.start();
thread.join();
thread1.join();
System.out.println(a.get());
}
}

方便吧;

2)实现自旋锁

CAS还能实现自旋锁的伪代码,为啥是伪代码,CAS毕竟CPU上的指令,java代码中没有具体的代码让我们看到,我们用伪代码的方式来呈现,

public class Demo1 {
private Thread t1 = null;
public void lock(){
while(!CAS(this.t1,null,Thread.currentThread())){};
}
public void unlock(){
this.t1 = null;
}
}

还记得什么是自旋锁吗,我们如果没有拿到当前线程会一直处于忙等的状态,直到拿到线程为止,我们这个代码就是,我们创建了一个线程,当这个线程要加锁的时候,我们看看当线程是不是为null,看看这个锁是不是被其他线程占有,如果t1不为null,那就继续循环,继续等待,直到,没人占用这个锁,就对当前线程加锁; 

3,CAS的ABA问题
1)什么是ABA问题

我们学过,CAS是CPU的一段指令,它的工作原理是比较和交换,既然是原子的那就完全没有线程安全问题了吗,我们来举一个极端的例子,我们把A改成B,之后另一个线程过来吧B改成A,我们第三个线程过来的时候看此时数据还是A,那不就是没改吗,可实际代码已经改过一次了;

2)ABA问题引来的BUG

我们在通常情况下ABA问题带来的影响是不大的,但是存在一种极端情况,我们现在有1000块钱,我们去ATM取钱,我们通常会狂按几下那个取款键,

3)解决方案

我们可以引入版本号,版本号只能加不能减,这样就能有效避免ABA问题了,类似一种标记吧;        

_____________________________________________________________________________

3,synchronized原理

1,基本特点

synchronized是自适应锁,JVM会统计每个锁的竞争激烈程度,如果竞争激烈,就会变成重量级的挂起等待锁(悲观),反之就是轻量级的自旋锁(乐观),

synchronized还是互斥锁,非公平锁,可重入锁;

2,加锁工作过程

锁升级,synchronized为啥优秀呢,它是能一步步升级为了应对不同的情况;

0)无锁

没加锁,还没进入synchronized的代码块;

1)偏向锁

进入synchronized之后并不真正的加锁,而是做一个标记,标记非常轻量,效率很高;

如果运行过程中,没有任何线程来抢竞争这个锁,一直运行到当前代码,最终解释代码时也只是清除标记,并没有涉及到真正的加锁和解锁;

2)轻量级锁

如果当前synchronized是偏向锁的时候,有锁想要竞争了,此时由只是做一个标记改为轻量级锁,赶在其他锁之前抢占它,其他锁去阻塞等待;

3)重量级锁

JVM发现锁的竞争十分激烈的时候就会把轻量级锁转换为重量级锁;

synchronized是不能降级的,只能升级;

我们来举一个好玩的例子,是我的老师给我们举的例子,比如我们是一个女生,我们和一堆男生搞暧昧,但是不确定关系,我们搞暧昧这个行为就相当于偏向锁,没有真正的加锁,但是当我们感觉到我们搞暧昧的男生要被人追走了的时候,我们就立刻和他确定关系,来完成加锁;

3,其他的优化操作
锁消除

锁消除也是编译器优化的一种体现,比如我们此时有一个线程,我们对代码去加锁,显然是没有必要的,虽然我们的代码上是这么写的,但是我们JVM在代码运行时就把他优化掉了;

锁粗化

锁的粒度,加锁和解锁中间包含的代码越多(这里只运行时间,执行的指令),锁的粒度就越粗,

什么意思呢,来看代码;

synchronized (object){
count++;
}
synchronized (object){
count++;
}
synchronized (object){
count++;
}
return count;
}

这就属于代码细粒度,JVM就会把让他粗度化,

synchronized (object){
count++;
count++;
count++;
}

这样的,这下大家理解了吧,编译器会帮助我们优化无意义的锁竞争, 给大家讲一个例子,我们给领导打电话的时候,我们要汇报工作情况,我们打电话,跟领导说,我第一个任务做的怎么怎么样,领导说好,我们挂断电话,之后再打电话,跟领导说我第二个任务做的怎么怎么样,领导说嗯,我们挂掉电话,继续打,跟领导说我们第三个任务........,领导..............;哈哈哈哈哈,是不是感觉到不合理了,我们应该一次电话把三次工作全部汇报完,这就是锁粗化存在的意义;

_____________________________________________________________________________

相关新闻

  • 重链抗体(IgG2、IgG3)与传统抗体的核心区别:从结构到功能的全方位解析
  • 重点行业数字化转型一图参透 - 智慧园区
  • RustDesk:免费开源的跨平台远程桌面解决方案

最新新闻

  • Fate/Grand Automata (FGA) 终极指南:如何快速上手FGO安卓自动战斗工具
  • 2026 年 6 月百达翡丽全国售后网点深度实地调研报告书 含迁店新开全部信息 - 百达翡丽中国服务中心
  • 2026合肥新能源汽车贴膜怎么选?4家授权门店专项测评 - 互联网科技品牌测评
  • 北京沿街商铺风机专项隔音怎么做?|静华轩隔音窗|隔绝餐饮门店排风、商场楼顶大功率排风、商铺外置设备轰鸣噪音,兼顾店内营业私密性、周边住户降噪防护,商用商铺风机设备批量隔声定制 - 维小达科技
  • S12X XGATE协处理器实现SCI中断驱动与环形缓冲区设计
  • i.MX 6处理器引脚复位状态解析:硬件设计中的关键细节与避坑指南

日新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号