CAS 和 Sychronized的在CPU密集计算情况下的博弈

2024-08-28 05:38

本文主要是介绍CAS 和 Sychronized的在CPU密集计算情况下的博弈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

很多时候听到使用CAS很优秀。。。

但是CAS是银弹吗?

从实现角度上,sychronized当线程获得不到锁的时候把线程挂起,而CAS不会挂起,而是继续重试。

比如下面的一个场景

i++ 的场景,以下代码是AtomicInteger的i++源码

  public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}

底层是用的就是unsafeCAS实现。

public static void main(String[] args) throws InterruptedException {AtomicInteger i = new AtomicInteger();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {long start = System.currentTimeMillis();for (int j = 0; j < 100000000; j++) {i.incrementAndGet();}long end = System.currentTimeMillis();System.out.println(end - start + " ms");}});t1.start();t1.join();}

测试1亿次计算(粗略计算),458ms,cpu差不过50%左右。(i7-8700)
那么也就是说1ms可以计算2000000(2百万次)


因为我们计算一次的时候,需要调用cas函数一次,
那么两个线程竞争的时候,可以得出线程1(成功了)调用了CAS1次,而线程2调用了CAS两次
其实,我们可以得出一个公式
f(1) = 1,
f(2) = 2- -加上重试失败的一次,
f(2) =3 --加上重试失败的两次,

f(n) = n
那么也就是说如果有200个线程(201核cpu)一致在重试的话,
200! = f(200) + f(199) +…+f(2)+f(1) = 20100次
相当于200个线程同时竞争的情况下,i++成功计算的是0.02ms。
这点时间是微不足道

但是再回想一下区别,synchronized会阻塞线程,或者说是挂起

因为java程序在挂起唤醒线程的时候需要从用户态切换到内核态,这是非常消耗资源的。

那么这个时间消耗是多少呢?

不得而知,相比于0.02ms应该还是大些,或者小一些。

以上的例子举的是运算极快(释放锁极快,成功率高)的场景

但是当存在成功率低的,或者是上面的例子丰富一下,造一个下面的

在这里插入图片描述
这个程序其实应该用long的

我把主线程睡了120s(),还没有算完。但是如果按照我们之前的一个线程一个线程的计算的话,500ms * 200 = 100s也能算完,并且CPU也不会满载。
所以这个时候使用sychronized是不是也很合适呢?

这篇文章主要是表示了我对线程阻塞和不阻塞对时间损耗的一些思考。场景可能有些模糊。欢迎拍砖!!!

注:当然synchronized现在也有自旋锁。

这篇关于CAS 和 Sychronized的在CPU密集计算情况下的博弈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113880

相关文章

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Java进程CPU使用率过高排查步骤详细讲解

《Java进程CPU使用率过高排查步骤详细讲解》:本文主要介绍Java进程CPU使用率过高排查的相关资料,针对Java进程CPU使用率高的问题,我们可以遵循以下步骤进行排查和优化,文中通过代码介绍... 目录前言一、初步定位问题1.1 确认进程状态1.2 确定Java进程ID1.3 快速生成线程堆栈二、分析

conda安装GPU版pytorch默认却是cpu版本

《conda安装GPU版pytorch默认却是cpu版本》本文主要介绍了遇到Conda安装PyTorchGPU版本却默认安装CPU的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录一、问题描述二、网上解决方案罗列【此节为反面方案罗列!!!】三、发现的根本原因[独家]3.1 p

Linux CPU飙升排查五步法解读

《LinuxCPU飙升排查五步法解读》:本文主要介绍LinuxCPU飙升排查五步法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录排查思路-五步法1. top命令定位应用进程pid2.php top-Hp[pid]定位应用进程对应的线程tid3. printf"%

宝塔安装的MySQL无法连接的情况及解决方案

《宝塔安装的MySQL无法连接的情况及解决方案》宝塔面板是一款流行的服务器管理工具,其中集成的MySQL数据库有时会出现连接问题,本文详细介绍两种最常见的MySQL连接错误:“1130-Hostisn... 目录一、错误 1130:Host ‘xxx.xxx.xxx.xxx’ is not allowed

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

判断PyTorch是GPU版还是CPU版的方法小结

《判断PyTorch是GPU版还是CPU版的方法小结》PyTorch作为当前最流行的深度学习框架之一,支持在CPU和GPU(NVIDIACUDA)上运行,所以对于深度学习开发者来说,正确识别PyTor... 目录前言为什么需要区分GPU和CPU版本?性能差异硬件要求如何检查PyTorch版本?方法1:使用命

浅析CSS 中z - index属性的作用及在什么情况下会失效

《浅析CSS中z-index属性的作用及在什么情况下会失效》z-index属性用于控制元素的堆叠顺序,值越大,元素越显示在上层,它需要元素具有定位属性(如relative、absolute、fi... 目录1. z-index 属性的作用2. z-index 失效的情况2.1 元素没有定位属性2.2 元素处

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES