cas 和 synchronized 优化过程

cas

什么是CAS

 CAS:全称Compareandswap,字⾯意思:”⽐较并交换“,⼀个CAS涉及到以下操作: 我们假设内存中的原数据V,旧的预期值A,需要修改的新值B。

 1. ⽐较A与V是否相等。(⽐较) 

2. 如果⽐较相等,将B写⼊V。(交换)

 3. 返回操作是否成功。

CAS伪代码 

下⾯写的代码不是原⼦的,真实的CAS是⼀个原⼦的硬件指令完成的.这个伪代码只是辅助理解CAS的⼯作流程.

boolean CAS(address, expectValue, swapValue) {if (&address == expectedValue) {&address = swapValue;return true;}return false;
}

CAS有哪些应用

1)实现原⼦类 

标准库中提供了ava.util.concurrent.atomic 包,⾥⾯的类都是基于这种⽅式来实现的. 典型的就是AtomicInteger类.其中的getAndIncrement相当于i++操作.

AtomicInteger atomicInteger = new AtomicInteger(0);
// 相当于 i++ 
atomicInteger.getAndIncrement();

伪代码实现:

class AtomicInteger {private int value;public int getAndIncrement() {int oldValue = value;while ( CAS(value, oldValue, oldValue+1) != true) {oldValue = value;}return oldValue;}
}

假设两个线程同时调⽤getAndIncrement 

1. 两个线程都读取value的值到oldValue中.(oldValue是⼀个局部变量,在栈上.每个线程有⾃⼰的栈)

2. 线程1先执⾏CAS操作.由于oldValue和value的值相同,直接进⾏对value赋值.

 注意:

 • CAS是直接读写内存的,⽽不是操作寄存器.

 • CAS的读内存,⽐较,写内存操作是⼀条硬件指令,是原⼦的.

3. 线程2再执⾏CAS操作,第⼀次CAS的时候发现oldValue和value不相等,不能进⾏赋值.因此需要 进⼊循环.

 在循环⾥重新读取value的值赋给oldValue

4. 线程2接下来第⼆次执⾏CAS,此时oldValue和value相同,于是直接执⾏赋值操作.

5. 线程1和线程2返回各⾃的oldValue的值即可.

 通过形如上述代码就可以实现⼀个原⼦类.不需要使⽤重量级锁,就可以⾼效的完成多线程的⾃增操作. 

本来checkandset这样的操作在代码⻆度不是原⼦的.但是在硬件层⾯上可以让⼀条指令完成这个 操作,也就变成原⼦的了.

synchronized

锁升级

JVM将synchronized锁分为⽆锁、偏向锁、轻量级锁、重量级锁状态。会根据情况,进⾏依次升 级。

1)偏向锁

 第⼀个尝试加锁的线程,优先进⼊偏向锁状态. 

偏向锁不是真的"加锁",只是给对象头中做⼀个"偏向锁的标记",记录这个锁属于哪个线程.

 如果后续没有其他线程来竞争该锁,那么就不⽤进⾏其他同步操作了(避免了加锁解锁的开销)

如果后续有其他线程来竞争该锁(刚才已经在锁对象中记录了当前锁属于哪个线程了,很容易识别当前 申请锁的线程是不是之前记录的线程),那就取消原来的偏向锁状态,进⼊⼀般的轻量级锁状态.

偏向锁本质上相当于"延迟加锁".能不加锁就不加锁,尽量来避免不必要的加锁开销. 但是该做的标记还是得做的,否则⽆法区分何时需要真正加锁.

2)轻量级锁

随着其他线程进⼊竞争,偏向锁状态被消除,进⼊轻量级锁状态(⾃适应的⾃旋锁). 此处的轻量级锁就是通过CAS来实现.

 • 通过CAS检查并更新⼀块内存(⽐如null=>该线程引⽤)

 • 如果更新成功,则认为加锁成功

 • 如果更新失败,则认为锁被占⽤,继续⾃旋式的等待(并不放弃CPU).

 ⾃旋操作是⼀直让CPU空转,⽐较浪费CPU资源. 因此此处的⾃旋不会⼀直持续进⾏,⽽是达到⼀定的时间/重试次数,就不再⾃旋了. 也就是所谓的"⾃适应"

3)重量级锁

 如果竞争进⼀步激烈,⾃旋不能快速获取到锁状态,就会膨胀为重量级锁 此处的重量级锁就是指⽤到内核提供的mutex.

 • 执⾏加锁操作,先进⼊内核态.

 • 在内核态判定当前锁是否已经被占⽤

 • 如果该锁没有占⽤,则加锁成功,并切换回⽤⼾态.

 • 如果该锁被占⽤,则加锁失败.此时线程进⼊锁的等待队列,挂起.等待被操作系统唤醒.

 • 经历了⼀系列的沧海桑⽥,这个锁被其他线程释放了,操作系统也想起了这个挂起的线程,于是唤醒 这个线程,尝试重新获取锁.

锁消除

编译器+JVM判断锁是否可消除.如果可以,就直接消除.

什么是"锁消除" 

有些应⽤程序的代码中,⽤到了synchronized,但其实没有在多线程环境下.(例如StringBuffer)

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

此时每个append的调⽤都会涉及加锁和解锁.但如果只是在单线程中执⾏这个代码,那么这些加锁解 锁操作是没有必要的,⽩⽩浪费了⼀些资源开销.

锁粗化

⼀段逻辑中如果出现多次加锁解锁,编译器+JVM会⾃动进⾏锁的粗化.

 锁的粒度:粗和细

实际开发过程中,使⽤细粒度锁,是期望释放锁的时候其他线程能使⽤锁.

但是实际上可能并没有其他线程来抢占这个锁.这种情况JVM就会⾃动把锁粗化,避免频繁申请释放锁.

举个栗⼦理解锁粗化

滑稽⽼哥当了领导,给下属交代⼯作任务:

 ⽅式⼀:

 • 打电话,交代任务1,挂电话.

• 打电话,交代任务2,挂电话.

• 打电话,交代任务3,挂电话. 

⽅式⼆:

 • 打电话,交代任务1,任务2,任务3,挂电话.

 显然,⽅式⼆是更⾼效的⽅案.可以看到,synchronized的策略是⽐价复杂的,在背后做了很多事情,⽬的为了让程序猿哪怕啥都不懂,也不⾄于写出特别慢的程序.JVM开发者为了Java程序猿操碎了心.

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

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

相关文章

半导体行业黑话-02

31. #Silicon Chef# - 硅厨师,指负责设计和制造芯片的工程师。 32. #Silicon Chefs Kitchen# - 硅厨师的厨房,指半导体设计和制造的实验室或工作区。 33. #Silicon Ghetto# - 硅贫民区,有时用来形容那些技术落后或条件较差的制造厂。 34. #Silicon Jungle# - 硅丛林,形容半…

ubuntu22.04单个网口两个IP

其中 4网段IP可用来上网,3 网段用来内网 界面显示: 配置文件: 01-network-manager-all.yaml 放在 /etc/netplan/ # Let NetworkManager manage all devices on this systemnetwork:version: 2renderer: networkdethernets:eth0:dhcp4: falsedhcp6: …

防火墙与入侵检测系统(IDS/IPS)在现代网络安全中的关键角色

在数字化日益加速的今天,网络安全变得尤为重要。随着网络攻击的复杂性和频率不断增加,保护关键信息资产已成为各大小组织的首要任务。防火墙(Firewall)和入侵检测系统(Intrusion Detection System,IDS&…

开放式耳机哪个牌子好?五大超值机型整理,速速收藏!!

大家都知道现在的开放式耳机是越来越火了,后台也有非常多的小伙伴来私信,作为一个耳机测评师,当然是为了你们服务啦,所以这一期文章,就是为了个大家答疑解惑,告诉大家如何才能选购出一款比较好用的开放式耳…

【Python】字母 Rangoli 图案

一、题目 You are given an integer N. Your task is to print an alphabet rangoli of size N. (Rangoli is a form of Indian folk art based on creation of patterns.) Different sizes of alphabet rangoli are shown below: # size 3 ----c---- --c-b-c-- c-b-a-b-c --…

3106. 满足距离约束且字典序最小的字符串 Medium

给你一个字符串 s 和一个整数 k 。 定义函数 distance(s1, s2) ,用于衡量两个长度为 n 的字符串 s1 和 s2 之间的距离,即: 字符 a 到 z 按 循环 顺序排列,对于区间 [0, n - 1] 中的 i ,计算所有「 s1[i] 和 s2[i] 之间…

万字长文详解Java反射技术 | JavaSE | Java进阶知识 | 源码

🙋大家好!我是毛毛张! 🌈个人首页: 神马都会亿点点的毛毛张 📌今天分享的是JavaSE中的进阶知识🛑:反射技术。内容有点长,非常全面,记得点赞👍、收藏✅加关…

最长回文字符串

# 状态转移方程 P(i,j)P(i1,j−1)∧(SiSj)class Solution:def longestPalindrome(self, s: str) -> str:n len(s)if n < 2:return smax_len 1begin 0# dp[i][j] 表示s[i..j]是否是回文串dp [[False] * n for _ in range(n)]for i in range(n):dp[i][i] True# 开始递…

【网络世界】HTTP协议

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 概念 &#x1f4c1; URL &#x1f4c2; urlencode 和 urldecode &#x1f4c1; 协议格式 &#x1f4c1; 方法 &#x1f4c2; GET/get &#x1f4c2; POST/post &#x1f4c1; 常见的报头 &#x1f4c1; 状态码 &…

模型大小的指标和模型量化的指标和手段

一、模型大小的指标 1.计算量 计算次数&#xff0c;反映了模型对硬件计算单元的需求。计算量的单位是 OPs(Operations) 。最常用的数据格式 为 float32&#xff0c;因此float32类型下的计算量单位被写作 FLOPs (Floating Point Operations)&#xff0c;即浮点计算次数。模型的…

3D Web轻量化引擎HOOPS Communicator针对复杂大模型Web端可视化的解决方案

随着工程设计、制造和建筑领域中三维模型的日益复杂化&#xff0c;如何在Web端高效处理和展示这些大规模数据成为一大挑战。HOOPS Communicator作为一款强大的3D可视化工具&#xff0c;提供了一套针对复杂大模型的轻量化解决方案&#xff0c;涵盖了模型轻量化及格式转换、超大模…

PostgreSQL成为最受欢迎的数据库; TiDB马拉松大赛开启, Serverless和Vector为比赛焦点

重要更新 1. TiDB Hackathon大赛报名开启&#xff0c;总奖金达21万&#xff0c;主题是基于 TiDB Serverless 内置的向量搜索功能&#xff08;Vector Search&#xff09;构建 AI 创新应用&#xff0c;感兴趣的可以报名参加。( [1] ) 2. Stack Overflow 2024 开发者调研结果公布…

自学JavaScript(放假在家自学第一天)

目录 JavaScript介绍分为以下几点 1.1 JavaScript 是什么 1.2JavaScript书写位置 1.3 Javascript注释 1.4 Javascript结束符 1.5 Javascript输入输出语法 JavaScript(是什么?) 是一种运行在客户端(浏览器)的编程语言&#xff0c;实现人机交互效果。 2.作用(做什么?)网…

NestedScrollVew实现原理分析

NestedScrollView 是 Android 中的一个特殊滚动视图&#xff0c;它继承自 ScrollView&#xff0c;但添加了对嵌套滚动&#xff08;nested scrolling&#xff09;的支持。这使得 NestedScrollView 可以与其它支持嵌套滚动的视图&#xff08;如 RecyclerView&#xff09;协同工作…

从头开始微调Llama 3.1模型

在今天的科技专栏中&#xff0c;我们将深入探讨如何微调Llama 3.1模型&#xff0c;以使其更好地适应您的特定领域数据。微调大型语言模型&#xff08;如Llama&#xff09;的主要目的是为了在特定领域的数据上表现更好&#xff0c;从而生成更符合您需求的输出。以下是我们将要介…

链表的中间结点 - 力扣(LeetCode)C语言

876. 链表的中间结点 - 力扣&#xff08;LeetCode&#xff09;( 点击前面链接即可查看题目) /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* middleNode(struct ListNode* head) {struct Lis…

如何实现一个大模型在回答问题时同时提供相关内容链接

通义生成 为了让大模型在回答问题时能够提供相关内容链接&#xff0c;通常采用的方法是结合检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;的技术。这种方法可以让大模型在生成答案的同时&#xff0c;从外部知识源中检索相关信息&#xff0c;并将这…

SpringBoot知识笔记

一、基本概念 1.1 特性 起步依赖 自动配置 其它特性:内嵌的Tomcat、Jetty(无需部署WAR文件),外部配置,不需要XML配置(properties/yml)。 1.2 配置文件 SpringBoot提供了多种属性配置方式 //application.properties server.port=9090 server.servlet.context-path…

状态模式与订单状态机的实现

状态模式 状态模式&#xff08;State Design Pattern&#xff09;是一种行为设计模式&#xff0c;用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中&#xff0c;使得对象在状态变化时不会影响到其他代码&#xff0c;提升了代码的灵活性和可维…

Python爬虫知识体系-----Urllib库的使用

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 1. 基本使用2. 请求对象的定制3. 编解码1. get请求方式&#xff1a;urllib.parse.quote&#xff08;&#xff09;2. ur…