Java:从单线程计数器到多线程数据同步synchronized和原子类Atomic
目录
- 使用单线程
- 使用多线程
- 使用多线程 + synchronized
- 使用多线程 + 原子类AtomicLong
使用单线程
单线程修改计数器的值,没有发生问题,每次运行结果都是10000,不过程序耗时较长
package com.example;/*** 计数器*/
class Counter {private static long count;public static long getCount() {return count;}public static void incrementCount() {count++;}
}public class Demo {public static void main(String[] args) throws InterruptedException {long count = Counter.getCount();System.out.println(count);// 0for (int i = 0; i < 10000; i++) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}Counter.incrementCount();}count = Counter.getCount();System.out.println(count);// 10000}
}
使用多线程
单线程修改计数器的值,运行速度提高了,不过运行结果每次都不一致,而且结果不是10000
package com.example;import java.util.ArrayList;
import java.util.List;/*** 计数器*/
class Counter {private static long count;public static long getCount() {return count;}public static void incrementCount() {count++;}
}public class Demo {public static void main(String[] args) throws InterruptedException {long count = Counter.getCount();System.out.println(count);// 0List<Thread> list = new ArrayList<>();// 启动10000个线程同时访问计数器for (int i = 0; i < 10000; i++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}Counter.incrementCount();}});list.add(thread);}for (Thread thread : list) {thread.start();}for (Thread thread : list) {thread.join();}count = Counter.getCount();System.out.println(count);}
}
执行结果
第一次:9910
第二次:9912
第三次:9910
使用多线程 + synchronized
多线程加锁后,最后结果都是10000
package com.example;import java.util.ArrayList;
import java.util.List;/*** 计数器*/
class Counter {private static long count;public static long getCount() {return count;}public static synchronized void incrementCount() {count++;}
}public class Demo {public static void main(String[] args) throws InterruptedException {long count = Counter.getCount();System.out.println(count);// 0List<Thread> list = new ArrayList<>();// 启动10000个线程同时访问计数器for (int i = 0; i < 10000; i++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}Counter.incrementCount();}});list.add(thread);}for (Thread thread : list) {thread.start();}for (Thread thread : list) {thread.join();}count = Counter.getCount();System.out.println(count);}
}
执行结果
第一次:10000
第二次:10000
第三次:10000
使用多线程 + 原子类AtomicLong
多线程中使用原子类AtomicLong实现计数器,最后结果都是10000
原理是CAS(Compare and Set):
- 先比较原始值和预期值,如果相等,则修改为新值;
- 不相等则修改失败
伪代码如下
bool compareAndSet(oldValue, expectValue, updateValue){if(oldValue == expectValue){oldValue = updateValue// update success} else{// update fail}
}
package com.example;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;/*** 计数器*/
class Counter {private static AtomicLong count = new AtomicLong(0);public static long getCount() {return count.get();}public static void incrementCount() {count.incrementAndGet();}
}public class Demo {public static void main(String[] args) throws InterruptedException {long count = Counter.getCount();System.out.println(count);// 0List<Thread> list = new ArrayList<>();// 启动10000个线程同时访问计数器for (int i = 0; i < 10000; i++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}Counter.incrementCount();}});list.add(thread);}for (Thread thread : list) {thread.start();}for (Thread thread : list) {thread.join();}count = Counter.getCount();System.out.println(count);}
}
执行结果
第一次:10000
第二次:10000
第三次:10000
参考
- 使用Atomic-廖雪峰的官方网站
- CAS锁机制(无锁、自旋锁、乐观锁、轻量级锁)
- java中的Atomic类
相关文章:
Java:从单线程计数器到多线程数据同步synchronized和原子类Atomic
目录 使用单线程使用多线程使用多线程 synchronized使用多线程 原子类AtomicLong 使用单线程 单线程修改计数器的值,没有发生问题,每次运行结果都是10000,不过程序耗时较长 package com.example;/*** 计数器*/ class Counter {private st…...
提前进入行业顶尖阵营:高性能计算实习的竞争优势
如今就业越来越内卷,尤其是计算机行业更是如此。加上GPT以及大模型的加持,各大企业纷纷降本增效,普通程序员逐渐失去竞争力。想要在竞争激烈的就业市场中脱颖而出,提前进入行业顶尖阵营是一个明智的选择。而高性能计算实习将为您提…...
Java程序设计入门教程--标识符和关键字
目录 标识符 标识符的约定 标识符 1. 定义 用来标识类名,变量名,方法名,类型名,数组名,文件名的有效序列称为标识符。简单地说,标识符就是一个名字。 2. 标识符命名规则 (1)大小…...
国产IC芯片自动化测试系统ATECLOUD,助力芯片测试自动化
IC芯片测试成本是影响制造和加工成本的重要因素。在某些情况下,测试成本可能占到器件总成本的40%左右。为了降低测试成本,可以优化测试程序并研发多工位测试。同时,必须平衡良品率和测试时间,以实现最佳的成本控制。本篇文章纳米软…...
BeanFactory和ApplicationContext有什么区别?
BeanFactory和ApplicationContext有什么区别? BeanFactory和ApplicationContext有什么区别? BeanFactory和ApplicationContext有什么区别? BeanFactory (轻量级) 和ApplicationContext(高级特性和框架)是Spring的两大核心接口,都…...
js的BOM对象中的window、location使用
说明:BOM的全称是Browser Object Model,浏览器对象模型,有Window(浏览器窗口)、Navigator(浏览器)、Screen(屏幕)、History(历史记录)和Location&…...
DAY 68 redis高可用的主从复制、哨兵、cluster集群
Redis 高可用 什么是高可用 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服…...
leetcode 1209 学会删除字符串
删除字符串的经典kotlin操作: val mTemp (temp.text).replace(Regex("℃"),"") 以下是题目! 1209. 删除字符串中的所有相邻重复项 II 提示 中等 174 相关企业 给你一个字符串 s,「k 倍重复项删除操作」将会从 s…...
JavaScript6
一、概念 ES6是JavaScript语言的标准。 新特性:let和const命令、变量的解构赋值、字符串函数对象数组等扩展。 环境准备:需要安装NodeJs。 二、新特性 1、let let命令用来声明变量。他的用法类似var,但所声明的变量,只在let命令…...
轻松安装Redis:不用担心配置问题
一、Centos安装Redis 1.安装 EPEL 源 Redis 不在 CentOS 官方仓库中,需要安装 EPEL 源才能访问到 Redis 软件包。运行以下命令安装 EPEL 源: sudo yum install epel-release 2.安装 Redis 使用以下命令安装 Redis: sudo yum install re…...
ChatGPT学习研究总结
目录 ChatGPT研究总结 一、程序接入用途不大 二、思考:如何构建一个类似ChatGPT的自定义模型 一些ChatGPT研究学习资料(来源网络) (1)一文读懂ChatGPT模型原理 (2)MATLAB科研图像处理——…...
SpringBoot枚举入参实战
文章目录 前言一、什么是枚举?二、枚举的优点三、枚举的缺点四、使用步骤1.代码实现1.1.枚举1.2.实体1.3.控制层 2.Postman测试2.1.Get请求2.1.1.枚举参数2.1.2.对象枚举属性参数 2.2.Post请求2.2.1.枚举参数2.2.2.对象枚举属性参数 2.3.Put请求2.3.1.枚举参数2.3.2…...
Ansible介绍
文章目录 Ansible介绍Ansible的架构为什么要有Ansible TowerAnsible Tower Ansible介绍 Ansible是一种自动化工具,可以用于自动化部署、配置和管理IT基础设施。它是一种基于Python的开源软件,提供了一个简单易用的语言和工具集,使得自动化管…...
GPT-4的免费使用方法分享
目录 方法1:使用Ora.sh的LLM应用 方法2:使用https://steamship.com 方法3:使用https://nat.dev 方法4:http://tdchat.vip 方法5:使用Poe网站或App 方法6:使用 Opencat App 方法7:使用https://Huggin…...
一个产品的诞生
一个产品的诞生 一个产品的诞生通常需要经历多个阶段,包括市场调研、产品设计、原型制作、测试和生产等。在市场调研阶段,公司会了解消费者的需求和市场趋势,以确定产品的定位和特点。在产品设计阶段,设计师会根据市场调研结果和…...
MQTT与传统的HTTP协议对比,优势在哪里呢?
HTTP是应用最为广泛和流行的协议。但是MQTT在过去的几年里迅速取得了进展。在讨论物联网开发的时候,开发者必须在这两者之间作出选择。 MQTT集中于数据,而HTTP集中于文档。HTTP是一个用于客户端-服务器计算的请求-响应协议,它并非总是为移动设…...
热榜!阿里出品2023版Java架构师面试指南,涵盖Java所有核心技能
最近很多粉丝朋友私信我说:熬过了去年的寒冬却没熬过现在的内卷;打开Boss直拒一排已读不回,回的基本都是外包,薪资还给的不高,对技术水平要求也远超从前;感觉Java一个初中级岗位有上千人同时竞争࿰…...
【小程序】封装时间选择组件:用单元格van-cell和插槽slot,包括起始时间和终止时间
效果 可以选择起始时间和终止时间,并显示。 时间选择器放在van-cell的value插槽中。 用的库: https://vant-contrib.gitee.io/vant-weapp/#/home https://dayjs.fenxianglu.cn/category/ 用的组件:Cell单元格、DatetimePicker时间选择、Pop…...
华为OD机试真题B卷 Java 实现【猜密码】
一、题目描述 小杨申请了一个保密柜,但是他忘记了密码。只记得密码都是数字,而且所有数字都是不重复的。 请你根据他记住的数字范围和密码的最小数字数量,帮他算下有哪些可能的组合,规则如下: 输出的组合都是从可选的数字范围中选取的,且不能重复;输出的密码数字要按照…...
沉淀-MYSQL
MYSQL学习 数据库操作 创建数据库 create database db_name; 删除数据库 drop database db_name; 选择/使用数据库 use db_name; 使用mysqladmin在终端执行 创建数据库 mysqladmin -u root -p create db_name Enter password:*** 删除数据库 mysqladmin -u root -p drop db…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
