八股整理之JUC篇

news2026/5/21 1:58:36
怎么保证多线程安全synchronized关键字:可以使用synchronized关键字来同步代码块或方法确保同一时刻只有一个线程可以访问这些代码。对象锁是通过synchronized关键字锁定对象的监视器(monitor来实现的。volatile关键字volatile关键字用于变量确保所有线程看到的是该变量的最新值而不是可能存储在本地寄存器中的副本。Lock接口和ReentrantLock类java.util.concurrent.locks.Lock接口提供了比synchronized更强大的锁定机制ReentrantLock是一个实现该接口的例子提供了更灵活的锁管理和更高的性能。原子类Java并发库java.util.concurrent.atomic提供了原子类如AtomicInteger、AtomicLong等这些类提供了原子操作可以用于更新基本类型的变量而无需额外的同步。线程局部变量ThreadLocal类可以为每个线程提供独立的变量副本这样每个线程都拥有自己的变量消除了竞争条件。并发集合:使用java.util.concurrent包中的线程安全集合如ConcurrentHashMap、ConcurrentLinkedQueue等这些集合内部已经实现了线程安全的逻辑。JUC工具类: 使用java.util.concurrent包中的一些工具类可以用于控制线程间的同步和协作。例如Semaphore和CyclicBarrier等。Java中有哪些常用的锁在什么场景下使用内置锁synchronized、ReentrantLock、读写锁ReadWriteLock、乐观锁和悲观锁、自旋锁synchronized 工作原理synchronized是Java提供的原子性内置锁这种内置的并且使用者看不到的锁也被称为监视器锁使用synchronized之后会在编译之后在同步的代码块前后加上monitorenter和monitorexit字节码指令他依赖操作系统底层互斥锁实现。他的作用主要就是实现原子性操作和解决共享变量的内存可见性问题。执行monitorenter指令时会尝试获取对象锁如果对象没有被锁定或者已经获得了锁锁的计数器1。此时其他竞争锁的线程则会进入等待队列中。执行monitorexit指令时则会把计数器-1当计数器值为0时则锁释放处于等待队列中的线程再继续竞争锁。synchronized是排它锁当一个线程获得锁之后其他线程必须等待该线程释放锁后才能获得锁而且由于Java中的线程和操作系统原生线程是一一对应的线程被阻塞或者唤醒时时会从用户态切换到内核态这种转换非常消耗性能。从内存语义来说加锁的过程会清除工作内存中的共享变量再从主内存读取而释放锁的过程则是将工作内存中的共享变量写回主内存。实际上大部分时候我认为说到monitorenter就行了但是为了更清楚的描述还是再具体一点。除了用synchronized还有什么方法可以实现线程同步使用ReentrantLock类、使用volatile关键字、使用Atomic类synchronized锁静态方法和普通方法区别锁的对象不同普通方法锁的是当前对象实例this。同一对象实例的synchronized普通方法同一时间只能被一个线程访问不同对象实例间互不影响可被不同线程同时访问各自的同步普通方法。静态方法锁的是当前类的class对象。由于类的class对象全局唯一无论多少个对象实例该静态同步方法同一时间只能被一个线程访问。作用范围不同普通方法仅对同一对象实例的同步方法调用互斥不同对象实例的同步普通方法可并行执行。静态方法对整个类的所有实例的该静态方法调用都互斥一个线程进入静态同步方法其他线程无法进入同一类任何实例的该方法。多实例场景影响不同普通方法多线程访问不同对象实例的同步普通方法时可同时执行。静态方法不管有多少对象实例同一时间仅一个线程能执行该静态同步方法。synchronized锁升级的过程讲一下快手一面整个升级路径是无锁→偏向锁→轻量级锁→重量级锁这是一个单向过程只能升级不能降级。这个机制的核心在于对象头中的MarkWord它会根据锁状态存储不同的信息通过其中的锁标志位来标识当前锁处于什么状态。首先是无锁状态。对象刚创建出来时没有任何线程访问此时MarkWord中存储的是对象的HashCode、分代年龄等信息锁标志位是01偏向标志位是0。这是对象的初始状态还没有涉及任何同步操作。需要注意的是一旦对象调用过hashCode方法它就无法进入偏向锁状态了因为偏向锁需要用MarkWord的空间来存储线程ID而hashCode也要占用这部分空间两者冲突。当第一个线程进入同步块时锁会升级到偏向锁。此时会通过CAS操作在对象头的MarkWord中记录该线程ID锁标志位保持01但偏向标志位变为1。之后这个线程再次进入同步块时只需简单判断MarkWord中的线程ID是否是自己如果是就直接进入完全不需要加锁解锁操作这就极大优化了单线程反复进入同步块的场景。但一旦有第二个线程尝试获取这个锁就说明出现了竞争偏向锁就会被撤销。撤销过程需要等到安全点暂停持有偏向锁的线程检查该线程是否还在执行同步代码然后清除偏向标记这个过程开销不小。撤销偏向锁后就进入轻量级锁阶段。这时JVM会在当前线程的栈帧中创建锁记录空间把对象头的MarkWord复制进去然后通过CAS操作尝试把对象头的MarkWord更新为指向锁记录的指针锁标志位变为00。如果CAS成功说明获取轻量级锁成功。如果失败说明有其他线程在竞争这时线程会进行自旋不断重试CAS操作期望在短时间内持有锁的线程能释放锁。自旋的本质是用CPU时间换取避免线程阻塞的开销所以只适合锁持有时间很短的场景。重量级锁就是传统的synchronized实现它依赖操作系统的互斥量Mutex来实现锁标志位变为10Mark Word指向Monitor对象。未获取锁的线程会被阻塞进入Monitor的等待队列这个过程需要从用户态切换到内核态由操作系统来调度线程的阻塞和唤醒开销非常大。但在竞争激烈、持锁时间长的场景下阻塞线程反而比自旋更节省CPU资源这就是为什么要升级为重量级锁。用空间换时间用复杂度换性能在JDK 15下synchronized 的实际升级路径已经简化为无锁 → 轻量级锁 → 重量级锁废弃偏向锁的主要原因是它让 JVM 实现过于复杂而现代应用尤其是 lambda、record、虚拟线程大行其道的场景很少再从偏向锁中获益。CAS 和 AQS 有什么关系CAS 和 AQS 两者的区别CAS是一种乐观锁机制它包含三个操作数内存位置V)、预期值A和新值B)。CAS操作的逻辑是如果内存位置的值等于预期值A则将其更新为新值B否则不做任何操作。整个过程是原子性的通常由硬件指令支持如在现代处理器上cmpxchg指令可以实现CAS 操作。AQS 是一个用于构建锁和同步器的框架许多同步器如ReentrantLock、Semaphore、CountDownLatch等都是基于 AQS 构建的。AQS 使用一个volatile的整数变量state来表示同步状态通过内置的FIFo队列来管理等待线程。它提供了一些基本的操作如acquire获取资源和release(释放资源)这些操作会修改state的值并根据state的值来判断线程是否可以获取或释放资源。AQS 的acquire操作通常会先尝试获取资源如果失败线程将被添加到等待队列中并阻塞等待。release操作会释放资源并唤醒等待队列中的线程。CAS 和 AQS 两者的联系CAS 为 AQS 提供原子操作支持Threadlocal作用原理具体里面存的key value是啥会有什么问题如何解决?ThreadLocal是Java中用于解决线程安全问题的一种机制它允许创建线程局部变量即每个线程都有自己独立的变量副本从而避免了线程间的资源共享和同步问题。ThreadLocal作用线程隔离ThreadLocal为每个线程提供了独立的变量副本这意味着线程之间不会相互影响可以安全地在多线程环境中使用这些变量而不必担心数据竞争或同步问题。降低耦合度在同一个线程内的多个函数或组件之间使用ThreadLocal可以减少参数的传递降低代码之间的耦合度使代码更加清晰和模块化。性能优势由于ThreadLocal避免了线程间的同步开销所以在大量线程并发执行时相比传统的锁机制它可以提供更好的性能。Java中想实现一个乐观锁都有哪些方式1、CASCompare and Swap操作2、版本号控制增加一个版本号字段记录数据更新时候的版本每次更新时递增版本号。在更新数据时同时比较版本号若当前版本号和更新前获取的版本号一致则更新成功否则失败。3、时间戳CAS 有什么缺点1、ABA问题ABA的问题指的是在CAS更新的过程中当读取到的值是A然后准备赋值的时候仍然是A但是实际上有可能A的值被改成了B然后又被改回了A这个CAS更新的漏洞就叫做ABA。只是ABA的问题大部分场景下都不影响并发的最终效果。Java中有AtomicStampedReference来解决这个问题他加入了预期标志和更新后标志两个字段更新时不光检查值还要检查当前的标志是否等于预期标志全部相等的话才会更新。就是新加一个版本号验证2、循环时间长开销大自旋CAS的方式如果长时间不成功会给CPU带来很大的开销。3、只能保证一个共享变量的原子操作只对一个共享变量操作可以保证原子性但是多个则不行多个可以通过AtomicReference来处理或者使用锁synchronized实现。为什么不能所有的锁都用CASCAS操作是基于循环重试的机制如果CAS操作一直未能成功线程会一直自旋重试占用CPU资源。在高并发情况下大量线程自旋会导致CPU资源浪费。volatile和sychronized比较Synchronized解决了多线程访问共享资源时可能出现的竞态条件和数据不一致的问题保证了线程安全性。Volatile解决了变量在多线程环境下的可见性和有序性问题确保了变量的修改对其他线程是可见的。Synchronized: Synchronized是一种排他性的同步机制保证了多个线程访问共享资源时的互斥性即同一时刻只允许一个线程访问共享资源。通过对代码块或方法添加Synchronized关键字来实现同步。Volatile:Volatile是一种轻量级的同步机制用来保证变量的可见性和禁止指令重排序。当一个变量被声明为Volatile时线程在读取该变量时会直接从内存中读取而不会使用缓存同时对该变量的写操作会立即刷回主内存而不是缓存在本地内存中。非公平锁吞吐量为什么比公平锁大公平锁在整个执行过程中线程会从运行状态切换到休眠状态再从休眠状态恢复成运行状态但线程每次休眠和恢复都需要从用户态转换成内核态而这个状态的转换是比较慢的所以公平锁的执行速度会比较慢。非公平锁获取锁不用遵循先到先得的规则从而避免了线程休眠和恢复的操作这样就加速了程序的执行效率。线程池拒绝策略除了默认的 AbortPolicy直接抛异常还有 CallerRunsPolicy让提交任务的主线程自己执行缓解压力、DiscardPolicy直接静默丢弃新任务、DiscardOldestPolicy丢弃队列里最旧的任务再提交新任务有线程池参数设置的经验吗核心线程数corePoolSize设置的经验CPU密集型corePoolSize CPU核数 1避免过多线程竞争CPUIO密集型corePoolSize CPU核数 x 2或更高具体看IO等待时间线程池和三个线程同时并发比有什么优势线程池的优势主要体现在资源复用降低开销线程创建销毁需要内核态操作如系统调用开销较大。线程池会复用核心线程避免频繁创建线程尤其在任务量大时能显著减少资源消耗。而三个固定线程若任务超过负载要么排队等待效率低要么需要临时新建线程开销高。控制并发强度避免资源耗尽线程池通过最大线程数和队列限制并发数防止线程无限制创建比如瞬间1000个任务直接创建1000个线程可能导致CPU内存耗尽)。而三个线程若面对突发大量任务要么处理不过来任务堆积)要么手动扩容线程难以控制)。任务管理更灵活线程池支持任务排队、优先级调度、拒绝策略等能应对任务峰值如秒杀场景的突发请求)。而三个线程的并发方式缺乏这些机制任务处理逻辑会和业务代码耦合如手动写队列、处理超时)。线程池中shutdown ()shutdownNow()这两个方法有什么作用shutdown调用后状态置为 SHUTDOWN已提交但未开始执行的队列任务仍会按顺序继续执行直到全部完成只对处于空闲等待状态的 worker线程调用interrupt()。此后不能再往线程池中添加任何任务否则将拋出RejectedExecutionException 异常而 shutdownNow 为STOP并试图停止所有正在执行的线程不再处理还在池队列中等待的任务当然它会返回那些未执行的任务。它试图终止线程的方法是通过调用Thread.interrupt() 方法来实现的但是这种方法的作用有限如果线程中没有sleep、wait、Condition、定时锁等应用interrupt()方法是无法中断当前的线程的。所以ShutdownNow()并不代表线程池就一定立即就能退出它可能必须要等待所有正在执行的任务都执行完成了才能退出。提交给线程池中的任务可以被撤回吗可以当向线程池提交任务时会得到一个Future对象。这个Future对象提供了几种方法来管理任务的执行包括取消任务。取消任务的主要方法是Future接口中的cancelboolean mayInterruptIfRunning方法。这个方法尝试取消执行的任务。参数mayInterruptIfRunning指示是否允许中断正在执行的任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2630057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…