CAS和synchronized原理

news2024/12/23 8:10:45

synchronized与CAS

  • Synchronized 原理
    • 加锁工作过程
    • 一些优化
  • CAS
    • 实现原子类
  • 小结

Synchronized 原理

  1. synchronized 既可以是乐观锁, 也可以是悲观锁.
  2. synchronized 既可以是轻量级锁, 也可以是重量级锁.
  3. synchronized 重量级锁是由系统的互斥锁实现的; 轻量级锁是基于自旋锁实现的.
  4. synchronized 是非公平锁(不会遵守先来后到).
  5. synchronized 是可重入锁(内部会记录哪个线程拿到了锁, 记录引用计数).
  6. synchronized 不是读写锁.

Synchronized的内部实现策略?
可能会产生一系列的"自适应"的过程, 叫做锁升级.
无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁.

加锁工作过程

  • 偏向锁: 偏向锁不会真的加锁, 只是做了一个标记.如果有别的线程来竞争了, 才会真的加锁.如果没有别的线程竞争, 就始终不会真的加锁.(能不加就不加)
  • 轻量级锁: synchronized通过自旋锁的方式实现轻量级锁.
    一个线程把锁占据之后, 另一个线程就会按照自旋的方式反复查询当前锁是否被释放了,
    但是, 如果这把锁的线程越来越多了(锁竞争更激烈了), 就会升级为重量级锁.

一些优化

  • 锁消除: 编译器会智能的判定当前代码是否要加锁, 如果你写了加锁, 实际上没有必要加锁, 就会把加锁操作自动删除掉.
  • 锁粗化: 锁的粒度?
    我们一般认为, 如果加锁操作中包含的实际要执行的代码越多, 就认为锁的粒度越大.
    锁的粒度越小, 并发程度就更高.
for(...) {
	synchronized (this) {
		count++;
	}
}

锁的粒度越大, 效率就越高.

synchronized (this) {
	for(...) {
		count++;
	}		
}

CAS

CAS(Compare and swap).
假设内存中的原数据V, 旧的预期值A, 需要修改的新值B.
1. 比较AV是否相等.
2. 如果比较相等,B写入V.
3. 返回操作是否成功.

使用CAS伪代码来辅助理解CAS的工作流程, 不是原子性代码.

// address: 内存地址. expectValue: 寄存器中的值. swapValue: 相等就替换的值
boolean CAS(address, expectValue, swapValue) {
	if(&address == expectValue) {
		&address = swapValue;
		return true;
	}
	return false;
}

但是这段代码逻辑, 是通过一条cpu指令完成的, 具备原子性, 就给我们编写线程安全代码, 打开了新大门.

实现原子类

标准库中提供了一组原子类, 最典型的是AtomicInteger类.
在这里插入图片描述

在这里插入图片描述

有两个构造方法.
// 设置初值为0
AtomicInteger();
// 设置初值为initialValue
AtomicInteger(int initialValue);

提供了一系列方法:

// 前置++
public final int getAndIncrement() {
	Atomically increments by one the current value.
	Returns:
	the previous value
}
// 前置--
public final int getAndDecrement() {
	Atomically decrements by one the current value.
	Returns:
	the previous value
}
// 后置++
public final int incrementAndGet() {
	Atomically increments by one the current value.
	Returns:
	the updated value
}
// 后置--
public final int decrementAndGet() {
	Atomically decrements by one the current value.
	Returns:
	the updated value
}
public class Demo28 {
    // 设置初值为0
    private static AtomicInteger count = new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                count.getAndIncrement();
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                count.getAndIncrement();
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
        System.out.println(count);
    }
}
// 结果是10000, 是原子性的.

下面使用伪代码实现原子类:

class AtomicInteger {
    private int value;
    // 前置++
    public int getAndIncrement() {
        int oldValue = value;
        while ( CAS(value, oldValue, oldValue+1) != true) {
            oldValue = value;
       }
        return oldValue;
   }
}
// oldValue, value, oldValue+1 都是寄存器中的值
// 如果value和oldValue相等, 就return oldValue
// 如果不等, 就把oldValue = value;

为啥会出现oldValue != value的情况呢??
因为很可能出现有别的线程穿插在两段代码之间, 把它修改了.
在这里插入图片描述
以上的图很好的描绘了如何修改代码的…

当两个线程并发的执行++操作时,如果不加任何限制,其一,就会出现串行化;
其二, 就会出现穿插, 会使结果出现问题.
通过加锁保证线程安全,强制避免穿插.
而原子类CAS保证线程安全,借助CAS来识别当前是否出现了穿插情况,如果没穿插,此时直接修改.
如果穿插了,就会重新回去内存中的值,再次尝试修改. 
多个CAS线程访问内存时,一定会有先后顺序的.
因为多个cpu在操作同一个资源, 也会涉及到锁竞争(指令级别的锁).synchronized实现的
锁要轻量许多(cpu内部实现的机制).

小结

本文讲述了synchronized的原理, 以及CAS实现原子类.
博主会在下篇博客中更新CAS实现自旋锁, 以及ABA问题和相关面试题.
希望有收获的小伙伴多多支持!

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

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

相关文章

Windows 安全中心:页面不可用 你的 IT 管理员已限制对此应用的某些区域的访问,并且你尝试访问的项目不可用。有关详细信息,请与 IT 支持人员联系。

问题 1&#xff1a;Windows 安全中心提示&#xff1a;【页面不可用 你的 IT 管理员已限制对此应用的某些区域的访问&#xff0c;并且你尝试访问的项目不可用。有关详细信息&#xff0c;请与 IT 支持人员联系。】 修复 Microsoft.SecHealthUI 方法 1&#xff1a;命令自动重装安…

linq select 和selectMany的区别

Select 和 SelectMany 都是 LINQ 查询方法&#xff0c;但它们之间有一些区别。 Select 方法用于从集合中选择特定的属性或对集合中的元素进行转换&#xff0c;并返回一个新的集合。例如&#xff1a; var numbers new List<int> { 1, 2, 3, 4, 5 }; var squaredNumbers…

sc2024项目consul

1. 什么是consul HashiCorp Consul是一款服务网络解决方案&#xff0c;可让团队管理服务之间以及内部部署和多云环境及运行时的安全网络连接。consul提供服务发现、服务治理、流量管理和对网络基础设施设备的自动更新。(添加链接描述)Consul使用Go语言开发 2. 功能 多数据中…

【PCL】教程global_hypothesis_verification 通过验证模型假设来实现 3D 对象识别与位姿估计...

测试程序1 milk.pcd milk_cartoon_all_small_clorox.pcd 终端输出1&#xff1a; Model total points: 12575; Selected Keypoints: 193 Scene total points: 307200; Selected Keypoints: 7739 [pcl::SHOTEstimation::computeFeature] The local reference frame is not valid!…

windows驱动开发-内存概述

“90%的程序问题都是由内存引起的&#xff0c;剩下的10%是使用内存引起的&#xff01;”这是一句非常经典的论证&#xff0c;实际上&#xff0c;在程序开发中&#xff0c;内存问题就是最大的问题&#xff0c;没有之一。 现代的计算机体系中&#xff0c;内存承载了太多的功能&a…

解决“该扩展程序未列在 Chrome 网上应用店中,并可能是在您不知情的情况下添加的”的方法

一、问题 安装插件出现时“该扩展程序未列在 Chrome 网上应用店中&#xff0c;并可能是在您不知情的情况下添加的” 二、解决方法 1、把需要安装的第三方插件&#xff0c;后缀.crx 改成 .rar&#xff0c;然后解压&#xff0c;得到一个文件夹 2、再打开chrome://extensions/谷歌…

Visual Studio Code使用

目录 1.python的调试 2.c的运行 方法1&#xff1a; 方法2&#xff1a; 3.c的调试 3.1调试方法一&#xff1a;先生成执行文件&#xff0c;再调试 3.2调试方法二&#xff1a;同时生成执行文件&#xff0c;调试 4.tasks.json 与launch.json文件的参考 4.1C生成执行文件tas…

linux之进程通信

目录 一、进程通信介绍 1.目的 2.发展 3.进程通信是什么&#xff0c;怎么通信&#xff1f; 二、管道 1.介绍 2.匿名管道 1.单向通信管道原理 2.代码实现 3.管道特征 4.管道的四种情况 5.管道的应用场景 使用管道实现一个简易版本的进程池 3.命名管道 1.思考 2.…

燃冬之yum、vim和你

了解了很多指令和权限&#xff0c;搞点真枪实弹来瞅瞅 学Linux不是天天就在那掰扯指令玩&#xff0c;也不是就研究那个权限 准备好迎接Linux相关工具的使用了么码农桑~ yum 软件包 什么是软件包呢&#xff1f; 首先来举个生活中常见点的例子&#xff1a;比如我的手机是华为…

PLC无线通讯技术在汽车喷涂车间机械手臂上的应用

一、项目背景 在汽车生产装配工艺中&#xff0c;机械臂目前已经广泛地应用于装配、搬运等工业生产中&#xff0c;在机械臂系列产品中&#xff0c;汽车喷漆自动控制喷涂机械装置以其独特的优势&#xff0c;能够根据油漆喷涂量的大小&#xff0c;严格控制喷嘴与喷漆面之间距离等…

【函数式接口使用✈️✈️】配合策略模式实现文件处理的案例

目录 &#x1f378;前言 &#x1f37b;一、功能描述 &#x1f37a;二、面向对象设计模式 &#x1f379;三、策略模式 &#x1f366;四、策略 VS 面向对象 &#x1f368;章末 &#x1f378;前言 小伙伴们大家好&#xff0c;上周初步了解了下函数式接口&#xff0c;Consume…

「最没存在感」港姐冠军入行10年不受捧,与相恋4年男友分手

昨日&#xff08;4月21日&#xff09;一众歌手艺人齐集红馆举行《全港运动全城跃动第九届全港运动会开幕礼》录影&#xff0c;TVB亦派出不少的歌手艺人小花表演。其中一部分是邵珮诗与黄婧灵大跳拉丁舞&#xff0c;同属身材丰满的二人跳起上来视觉极夸张。 而平常经常露出姣好身…

powershell@命令行提示符样式配置自定义@pwsh重写prompt显示电量内存时间等信息

文章目录 abstract流行的powershell prompt模块示例 powershell原生修改Prompt函数配置文档Prompt命令来自哪里 简单修改带上电量和时间的Prompt 复杂修改预览FAQ:没有必要修改相关仓库地址样式选择平衡样式花哨样式响应性能 小结 abstract 在 PowerShell 中&#xff0c;可以通…

【git】git ignore如何添加core/config.py忽略

在Git中&#xff0c;.gitignore文件用于指定不被Git追踪的文件和文件夹。要添加core/config.py文件到.gitignore中&#xff0c;你需要编辑.gitignore文件并添加以下行&#xff1a; core/config.py这行表示Git应该忽略名为config.py的文件&#xff0c;它位于core目录下。确保在…

Codeforces Round 821 (Div. 2) D2. Zero-One

题目 #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e5 5, inf 1e18, maxm 4e4 5; const int N 1e6;c…

vue项目前端axios跨域请求处理问题

在我的服务器里面新建了一个txt文档&#xff0c;但在vue项目里面对这个文档发起请求的时候因为是ip地址请求&#xff0c;跨域请求失败&#xff0c;在配置了vue.config.js的请求代理后得以解决 报错示例&#xff1a; 解决方法&#xff1a; 1、在vue.config.js中配置跨越请求代…

microk8s拉取pause镜像卡住

前几天嫌服务器上镜像太多占空间&#xff0c;全部删掉了&#xff0c;今天看到 microk8s 更新了 1.30 版本&#xff0c;果断更新&#xff0c;结果集群跑不起来了。 先通过 microk8s.kubectl get pods --all-namespaces 命令看看 pod 状态。 如上图可以看到&#xff0c;所有的业…

【触摸案例-触摸事件介绍 Objective-C语言】

一、触摸事件 1.接下来,我们来说这个,触摸事件, iOS当中的事件,可以分为三大类: 1)触摸事件 2)加速计事件 3)远程控制事件 事件呢,这个里面呢,使用app的过程当中呢,产生各种各样的事件,事件呢,分为三大类,在iOS里边儿啊,分为三大类,首先,有一个叫做触摸事…

NLP大模型的训练

NLP模型的训练主要分成两步&#xff1a; 1.先进行通用任务的训练&#xff1b;无监督的样本是无穷无尽的&#xff1b; 这里列举两种&#xff1a;MLM和NSP,NSP由于在某些论文中被证明是无效的&#xff0c;所以用的少&#xff1b; MLM: 接下来会在特定任务上进行finetune>su…

Nacos分布式配置中心

<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 https://…