【Java并发】聊聊LongAdder应用场景及其原理

news2024/11/20 7:17:00

应用场景

我们知道在实际的应用场景中,可能会对某个商品进行浏览次数进行迭代,或者抖音视频的点击,那么如何高效记录呢,首先如果是使用普通的num 进行多线程操作的话,那么一定会带来数据一致性问题,所以一般通过syn\lock,但是因为有加锁和解锁的操作,以及线程竞争过多的时候,导致线程上下切换。那么又没有一种高效的方式呢,就是使用无锁编程原子类,atomicInteger但是因为是使用CAS并且针对的是同一个数据进行cas操作,操作数据的粒度是一个,所以进一步的方式是使用longAdder,主要原理就是将数据的操作粒度分散,类似于hashmap的散列表方式。

code


/**
 * @author qxlx
 * @date 2023/10/15 9:52 AM
 */

class MyNumber {

    public Long num = new Long(0);

    public synchronized long synAddNumer() {
        return num++;
    }

    public AtomicInteger atomicInteger = new AtomicInteger(0);

    public int atomicIntegerAddNumer() {
        return atomicInteger.getAndIncrement();
    }

    public LongAdder longAdder = new LongAdder();
    public int longAdderAddNumber(){
        longAdder.increment();
        return longAdder.intValue();
    }

}

public class LongAddrCalcDemo {

    public static final int THREAD_NUM = 50;
    public static final int ADD_NUM = 1000000;

    public static void main(String[] args) throws InterruptedException {
        MyNumber myNumber = new MyNumber();
        StopWatch stopWatch = new StopWatch();

        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
        CountDownLatch countDownLatch2 = new CountDownLatch(THREAD_NUM);
        CountDownLatch countDownLatch3 = new CountDownLatch(THREAD_NUM);

        stopWatch.start("1.加锁方式耗时");
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(()-> {
                for (int j = 0; j < ADD_NUM ; j++) {
                    long numer = myNumber.synAddNumer();
                }
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("1.加锁方式,num:"+myNumber.num);
        stopWatch.stop();


        stopWatch.start("2.atomic");
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(()-> {
                for (int j = 0; j < ADD_NUM ; j++) {
                    long numer = myNumber.atomicIntegerAddNumer();
                }
                countDownLatch2.countDown();
            }).start();
        }
        countDownLatch2.await();
        System.out.println("2.atomic,num:"+myNumber.atomicInteger);
        stopWatch.stop();


        stopWatch.start("3.longadder");
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(()-> {
                for (int j = 0; j < ADD_NUM ; j++) {
                    long numer = myNumber.longAdderAddNumber();
                }
                countDownLatch3.countDown();
            }).start();
        }
        countDownLatch3.await();
        System.out.println("3.longadder,num:"+myNumber.longAdder);
        stopWatch.stop();

        System.out.println("date:"+stopWatch.prettyPrint());
    }

}

在这里插入图片描述

原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

源码解读

在这里插入图片描述

   public void add(long x) {
        Cell[] as; long b, v; int m; Cell a;
        if ((as = cells) != null || !casBase(b = base, b + x)) {
            boolean uncontended = true;
            if (as == null || (m = as.length - 1) < 0 ||
                (a = as[getProbe() & m]) == null ||
                !(uncontended = a.cas(v = a.value, v + x)))
                longAccumulate(x, null, uncontended);
        }
    }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

【Unity基础】6.动画状态机

【Unity基础】6.动画状态机 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity基础系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;Animator Controller组件 &#xff08;1&#xff09;创建组件 Animator Controller组件是unity用于控制管…

【细读经典】delay model and timing analysis

Technology-Dependent LogicOptimization, part 1 序言 如图所示是现代工业流程中对于一个高层次的抽象描述如何到最后的芯片的流程图&#xff0c;其中逻辑综合作为一个非常重要的部分&#xff0c;主要被分为两个阶段&#xff1a; 工艺无关的优化(technology-independent opt…

shell脚本学习笔记03(小滴课堂)

在shell脚本中&#xff0c;表示变量除了可以使用$a(a是一个变量)&#xff0c;还可以使用${a} 那这两种表示方式有什么区别么&#xff1f; 花括号可以和其它字符或者字母区分开来。 >追加内容 我们发现使用>会把原来的内容覆盖。 我们使用>>就不会覆盖了&#xff…

MAYA教程之模型的UV拆分与材质介绍

什么是UV 模型制作完成后&#xff0c;需要给模型进行贴图&#xff0c;就需要用到UV功能 UV编译器介绍 打开UI编译器 主菜单有一个 UV->UV编译器&#xff0c;可以点击打开 创建一个模型&#xff0c;可以看到模型默认的UV UV编译器功能使用 UV模式的选择 在UV编译器中…

从裸机启动开始运行一个C++程序(八)

前序文章请看&#xff1a; 从裸机启动开始运行一个C程序&#xff08;七&#xff09; 从裸机启动开始运行一个C程序&#xff08;六&#xff09; 从裸机启动开始运行一个C程序&#xff08;五&#xff09; 从裸机启动开始运行一个C程序&#xff08;四&#xff09; 从裸机启动开始运…

【C++】C++11 ——lambda表达式

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C学习 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C】C11…

阿里云香港云服务器公网带宽价格表及测试IP地址

阿里云服务器香港地域公网带宽价格表&#xff0c;1M带宽价格是30.0元/月&#xff0c;按使用流量1GB价格是1.0元&#xff0c;阿里云香港服务器测试IP地址&#xff1a;47.75.18.101&#xff0c;阿里云百科aliyunbaike.com来详细说下阿里云香港服务器1M带宽、5M带宽、6M带宽、10M带…

民宿酒店订房房态商城小程序的作用是什么

外出旅游出差&#xff0c;酒店民宿总是很好的选择&#xff0c;随着经济复苏&#xff0c;各地旅游及外出办公人次增多&#xff0c;酒店成绩随之增加&#xff0c;市场呈现多品牌酒店经营形式。 区别于以前&#xff0c;如今互联网深入各个行业&#xff0c;酒店经营也面临着困境。…

删除字符串特定的字符(fF)C语言

代码&#xff1a; #include <stdio.h> void funDel(char *str) {int i, j;for (i j 0; str[i] ! \0; i)if (str[i] ! f && str[i] ! F)str[j] str[i];str[j] \0; }int main() {char str[100];printf("请输入一个字符串&#xff1a;");gets(str);pr…

转化限制+分析变量变化引起的答案变化:Gym - 104065D

https://vjudge.net/contest/587311#problem/H 先转化一波条件&#xff1a; p i ≥ 1 X p_i\ge \frac 1 X pi​≥X1​ p i ≤ 1 1 − Y p_i\le \frac 1 {1-Y} pi​≤1−Y1​ 所以我们按 p p p 排序&#xff0c; s u m x sum_x sumx​ 必然是后缀&#xff0c; s u m y sum_y …

Python算术运算符:加减乘除 整除 取余 幂指数 小括号

运算案例 需求&#xff1a;用户手工输入梯形的上底、下底以及高&#xff0c;能直接通过Python打印出梯形的面积为多少。 做这个需求前&#xff0c;首先要知道Python的算数运算符有哪些。 2、算术运算符 所谓的算数运算符就是我们日常生活中的加减乘除等待。 运算符描述实例…

汉服商城小程序的作用是什么

汉服在日常生活中越来越常见&#xff0c;大街小巷也有不少年轻人装扮甚是漂亮帅气&#xff0c;有些地区甚至还有相关的比赛等&#xff0c;作为近几年曝光的服饰&#xff0c;汉服市场规模持续增加中&#xff0c;各地线上线下商家也多了起来。 然而在实际经营中&#xff0c;汉服…

Anylogic 读取和写入Excel文件

1、选择面板-连接-Excel文件&#xff0c;拖入到视图中 然后在excel文件的属性中进行绑定外部excel文件。 绑定完之后&#xff0c;在你需要读取的地方进行写代码&#xff0c; //定义开始读取的行数 //这里设为2&#xff0c;是因为第一行是数据名称 int row12; //读取excel文件信…

SpringBoot-黑马程序员-学习笔记(六)

目录 76.常用计量单位使用 77.bean属性校验 81.测试表现层 82.发送虚拟请求 94.springboot读写redis的客户端 100.ElasticSearch&#xff08;简称ES&#xff09; 一个分布式全文搜索引擎 76.常用计量单位使用 Data Component ConfigurationProperties(prefix "serve…

SpringMVC的响应处理

目录 传统同步业务数据的响应 请求资源转发 请求资源重定向 响应数据模型 直接回写数据给客户端 前后端分离异步业务数据响应 在前面的文章中&#xff0c;我们已经介绍了Spring接收请求的部分&#xff0c;接下来看Spring如何给客户端响应数据 传统同步业务数据的响应 准…

Matlab统计棋盘连通分量(空值区域)的大小和个数

一、基础设定 在20x20的棋盘矩阵中&#xff0c;设定黑子为1&#xff0c;空值为0 现需要统计空值&#xff08;连通分量&#xff09;的大小和个数并标记&#xff0c;如下图所示&#xff1a; 以此类推 其中&#xff0c;最大的连通分量如下&#xff1a; 二、Matlab程序 以下是红…

读写锁ReentrantReadWriteLockStampLock详解

如何设计一把读写锁&#xff1f;ReentrantReadWriteLock 读写锁设计思路 读写状态的设计 设计的精髓&#xff1a;用一个变量如何维护多种状态 在 ReentrantLock 中&#xff0c;使用 Sync ( 实际是 AQS )的 int 类型的 state 来表示同步状态&#xff0c;表示锁被一个线程重复获…

【网络基础】——传输层

目录 前言 传输层 端口号 端口号范围划分 知名端口号 进程与端口号的关系 netstat UDP协议 UDP协议位置 UDP协议格式 UDP协议特点 面向数据报 UDP缓冲区 UDP的使用注意事项 基于UDP的应用层协议 TCP协议 TCP简介 TCP协议格式 确认应答机制&#…

性能测试需求分析

1、客户方提出 客户方能提出明确的性能需求&#xff0c;说明对方很重视性能测试&#xff0c;这样的企业一般是金融、电信、银行、医疗器械等&#xff1b;他们一般对系统的性能要求非常高&#xff0c;对性能也非常了解。提出需求也比较明确。 曾经有一个银行项目&#xff0c;已经…

漏洞复现--华测监测预警系统2.2任意文件读取

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…