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

相关文章

浅析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

Java的volatile和sychronized底层实现原理解析

《Java的volatile和sychronized底层实现原理解析》文章详细介绍了Java中的synchronized和volatile关键字的底层实现原理,包括字节码层面、JVM层面的实现细节,以... 目录1. 概览2. Synchronized2.1 字节码层面2.2 JVM层面2.2.1 ente

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

MySQL进阶之路索引失效的11种情况详析

《MySQL进阶之路索引失效的11种情况详析》:本文主要介绍MySQL查询优化中的11种常见情况,包括索引的使用和优化策略,通过这些策略,开发者可以显著提升查询性能,需要的朋友可以参考下... 目录前言图示1. 使用不等式操作符(!=, <, >)2. 使用 OR 连接多个条件3. 对索引字段进行计算操作4

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

MySQL的cpu使用率100%的问题排查流程

《MySQL的cpu使用率100%的问题排查流程》线上mysql服务器经常性出现cpu使用率100%的告警,因此本文整理一下排查该问题的常规流程,文中通过代码示例讲解的非常详细,对大家的学习或工作有一... 目录1. 确认CPU占用来源2. 实时分析mysql活动3. 分析慢查询与执行计划4. 检查索引与表

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2