[Java 进阶面试题] CAS 和 Synchronized 优化过程

news2024/11/16 15:34:45

最有用的东西,是你手里的钱,有钱就有底气,还不快去挣钱~

文章目录

  • CAS 和 Synchronized 优化过程
  • 1. CAS
    • 1.1 CAS的原理
    • 1.2 CAS实现自增自减的原子性
    • 1.3 CAS实现自旋锁
    • 1.4 CAS针对ABA问题的优化
  • 2. synchronized
    • 2.1 synchronized加锁阶段分析
    • 2.2 synchronized优化



CAS 和 Synchronized 优化过程

1. CAS

1.1 CAS的原理

CAS的具体操作是,有一个变量值i为A,想要将值A修改为新值B.
1.compare: 比较 if( i == A ).
2.swap : 如果相等,就把i的值改为B
3.返回此操作是否成功
CAS操作具有原子性,即这三个操作会通过一个指令完成三条操作,在一定程度上规避了线程安全问题.

1.2 CAS实现自增自减的原子性

如下代码,AtomicInteger,AtomicLong等类运用了CAS机制,实现变量自增自减的原子性.
a.getAndIncrement(); //a++
a.getAndDecrement(); //a–
a.incrementAndGet(); //++a
a.decrementAndGet(); //- -a
a.addAndGet(3); //a += 3

import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
public class MyAtomicInteger {
    public static void main(String[] args) throws InterruptedException{
        //AtomicInteger,AtomicLong,AtomicBoolean,AtomicIntegerArray
        AtomicInteger a = new AtomicInteger(0);
        Thread t1 = new Thread(()->{
            a.getAndIncrement();   //a++
            a.getAndDecrement();   //a--
            a.incrementAndGet();   //++a
            a.decrementAndGet();   //--a
            a.addAndGet(3);        //a += 3
        });
        Thread t2 = new Thread(()->{
            a.getAndIncrement();
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(a.get());
    }
}

1.3 CAS实现自旋锁

如下图,是CAS实现自旋锁的伪代码
while(!CAS(this.owner,null,Thread.currentThread()))
1.线程owner初始化为null
2.进入循环,先判断线程owner是否为null,如果owner不为空,代表owner正在被其他线程占用,则需要阻塞等待.
3.线程解锁后,又被设为null,这时可以把当前线程赋值给owner.
在这里插入图片描述

1.4 CAS针对ABA问题的优化

CAS的核心机制,检查变量i和旧值A是否相等,但如果变量i中途被修改了,后来又恢复成了A,系统是无法察觉的.
例如去银行取钱,原来1000,要取出500.银行系统慢,这个人多点了两下取钱键.
1.先比较钱数是否为1000,是,取出500.
2.但取钱的同时有位有人给卡充了500,使钱恢复成了1000
3.系统第二次比较,发现钱是1000,又取出了500
很明显,在这卡bug呢.

优化机制
给操作加一个版本号,每执行一次操作,版本号加1.执行的次数以版本号为主.就不会出现执行多次的情况

2. synchronized

2.1 synchronized加锁阶段分析

synchronized加锁有一个过程
1.无锁状态
2.偏向锁,先给要加锁的对象一个标记,看对象是否存在锁竞争,若执行过程中没有出现锁竞争,在执行synchronized之后取消偏向锁即可.如果出现另外的线程去竞争锁,需要迅速把偏向锁升级成真正的加锁状态.
3.轻量级锁,当synchronized发生锁竞争时,偏向锁升级为轻量级锁(加锁方式为自旋锁).
4.如果一直拿不到锁,自旋了一定时间后,锁就会升级为重量级锁(挂起等待锁).进入阻塞队列等待,直到锁被释放,线程才有机会获取锁.
注意:锁只能升级,没办法降级.

2.2 synchronized优化

1.锁清除
对对象加锁后,编译器可以去自动判定,若当前场景不需要加锁,编译器会把锁清除.
2.锁粗化
如果一段代码中,出现了多个锁,加锁解锁频繁,并且每个锁之间距离很近.这时可以用一个大锁直接包含这些小锁,减少频繁加锁解锁的开销.

本文完


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

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

相关文章

nodejs+vue大学生在线选课系统vscode - Visual Studio Code

3、数据库进行设计,建立约束和联系。 4、创建程序框架,代码分成三层结构:接口层、业务层、表示层,设计窗口和主窗口,主窗口菜单项依照系统模块图设计。 5、设计数据访问的接口,供各模块调用。完成登录功能…

【JavaWeb项目】简单搭建一个前端的博客系统

博客系统项目 本项目主要分成四个页面: 博客列表页博客详情页登录页面博客编辑页 该系统公共的CSS样式 common.css /* 放置一些各个页面都会用到的公共样式 */* {margin: 0;padding: 0;box-sizing: 0; }/* 给整个页面加上背景 */ html, body{height: 100%; }body {backgrou…

printf的返回值

参考资料 点击下面的链接https://legacy.cplusplus.com/reference/cstdio/printf/?kwprintf, 返回值的理解 如果返回成功后,将返回写入的字符总数。 如果发生写入错误,则设置错误指示器(ferror)并返回负数。 如果在写入宽字符…

微信中如何接入chatgpt机器人才比较安全(不会收到警告或者f号)之第一步登录微信

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。 前言 为什么会有这个话题?大家都知道最近有个AI机器人很火,那就是chatgpt,关于它的介绍,大家可以自行百度去,我这边就不多介绍了。 好多人嫌网页版玩的不过瘾,就把这个机器人接入到了QQ上,接入到了钉钉上,TG 上…

设计模式:原型模式解决对象创建成本大问题

一、问题场景 现在有一只猫tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和tom猫属性完全相同的10只猫。 二、传统解决方案 public class Cat {private String name;private int age;private String color;…

JMeter 接口测试/并发测试/性能测试

Jmter工具设计之初是用于做性能测试的,它在实现对各种接口的调用方面已经做的比较成熟,因此,本次直接使用Jmeter工具来完成对Http接口的测试。因为再做接口测试时可以设置线程组,所以也可做接口性能测试。本篇使用JMeter完成了一个…

TrueNas篇-trueNas Scale安装

安装TrueNAS Scale 在尝试trueNas core时发下可以成功安装,但是一直无法成功启动,而且国内对我遇见的错误几乎没有案例,所以舍弃掉了,而且trueNas core是基于Linux的,对Linux的生态好了很多,还可以可以在t…

DNS 原理入门指南(二)

三、DNS服务器 下面我们根据前面这个例子,一步步还原,本机到底怎么得到域名math.stackexchange.com的IP地址。 首先,本机一定要知道DNS服务器的IP地址,否则上不了网。通过DNS服务器,才能知道某个域名的IP地址到底是什么…

Qt优秀开源项目之十六:SQLite数据库管理系统—SQLiteStudio

首先,感谢CSDN官方认可 SQLiteStudio是一款开源、跨平台(Windows、Linux和MacOS)的SQLite数据库管理系统。 github地址:https://github.com/pawelsalawa/sqlitestudio 官网:https://sqlitestudio.pl/ 特性很多&#xf…

11-git-查看提交历史

查看提交历史前言查看提交历史常用选项-p-n--stat--pretty--since限制输出选项前言 本篇来学习git中查看提交历史命令 查看提交历史 官方项目例子: git clone https://github.com/schacon/simplegit-progit git log说明: 不传任何参数会按时间先后顺序列出所有的…

Springboot+jsp齐鲁历史文化名人网站

山东地区是齐鲁文化的发源地,也是中华文明的摇篮之一 ,早在四十万年前这里 就开始出现了人类活动的遗迹(发现于沂源骑子鞍山南麓的沂源猿人头骨化石就是最好的证据)。另外,山东省境内的新泰、长岛、日照、蓬莱等地也都发现了旧石器时代晚期的人类化石。目前,山东史前文化的发掘…

C语言fopen函数的用法

在C语言中,操作文件之前必须先打开文件;所谓“打开文件”,就是让程序和文件建立连接的过程。打开文件之后,程序可以得到文件的相关信息,例如大小、类型、权限、创建者、更新时间等。在后续读写文件的过程中&#xff0c…

Selenium常用API详解,从入门到进阶(全套)

目录 1、打开页面 2、查找页面元素 3、输入文本 4、点击操作 5、提交操作 6、清除文本 7、获取文本、属性 8、获取页面的标题和URL 9、窗口 9.1、设置窗口大小 9.2、窗口切换 9.2.1、为什么需要窗口切换? 9.2.2、获取句柄的方式 9.2.3、切换句柄 10、…

秒杀项目之商品展示及商品秒杀

目录 登录方式调整 生成秒杀订单 绑定秒杀商品 查看秒杀商品 订单秒杀 移除seata相关 生成秒杀订单 前端页面秒杀测试 登录方式调整 第1步:从zmall-common的pom.xml中移除spring-session-data-redis依赖 注意: 1)本章节中不采用spri…

Python获取搜索引擎结果

前言 想快速获取各个高校的博士招生网站,于是通过python先获取出有可能包含高校博士招生网站的URL,然后通过人为筛选得到了想要的招生网站(注意,并非直接爬取,是间接获取的)。 整理了一份网站名单&#x…

ModSecurity网站防火墙安装教程加WEB防御规则设置

ModSecurity安装教程加核心防御规则 资源宝分享:www.httple.net ModSecurity简介 ModSecurity-官网: ​​http://www.modsecurity.cn​​ ModSecurity是目前世界上使用最多的开源WAF产品,可谓是WAF界的鼻祖,跨平台的Web应用防火墙&#xff08…

学习open62541 --- [75] 生成namespace文件的简便方法

在之前的文章中,生成namespace文件是使用open62541提供的nodeset_compiler.py,根据nodeset_compiler.rst(位于open62541/doc/)里的描述,有更好的方法:使用cmake命令ua_generate_nodeset_and_datatypes来生成…

ChatGPT可以写文章吗?来看看他对卷积神经网络的解释是否准确

文章目录提问chatGPT的回答第一次回答第二次回答结果提问 chatGPT的回答 在回答时候由于字数限制它不能一口气输出全部结果,此时可以采用两种方法让它继续输出: 复制它的上一步回答给它,它会接着回复直接发送继续,它也会接着回复…

体验100问 | 「体验管理」是一个正确的职业选择吗?

Guofu 第 84⭐️ 篇原创干货分享(点击👆🏻上方卡片关注我,加⭐️星标⭐️~)Q003:体验管理是一个正确的职业选择吗?🤔 龙国富说: 1、职业选择应该去寻求“不变”的事情这件事其实在我…

DS期末复习卷(三)

选择题 某数据结构的二元组形式表示为A(D&#xff0c;R)&#xff0c;D{01&#xff0c;02&#xff0c;03&#xff0c;04&#xff0c;05&#xff0c;06&#xff0c;07&#xff0c;08&#xff0c;09}&#xff0c;R{r}&#xff0c;r{<01&#xff0c;02>&#xff0c;<01&a…