多线程学习篇三:共享带来的问题及解决方案

1. 共享带来的问题

1.1 案例演示

两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?

@Slf4j(topic = "c.Sync01")
public class Sync01 {private static int COUNTER = 0;public static void increment() {COUNTER++;}public static void decrement() {COUNTER--;}public static void main(String[] args) throws Exception {Thread t1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {increment();}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {decrement();}}, "t2");t1.start();t2.start();t1.join();t2.join();log.info("COUNTER = {}", COUNTER);}
}

1.2 运行结果

1.2.1 结果为负

1.2.2 结果为正

1.2.3 结果为 0

2. 从字节码分析问题

以上的结果可能是正数、负数、零。为什么呢?因为 Java 中对静态变量的自增、自减并不是原子操作,要彻底理解,必须从字节码来进行分析

2.1 increment 相关字节码

public static void increment();Code:0: getstatic     #2   // 获取静态变量COUNTER的值3: iconst_1           // 准备常量14: iadd               // 自增5: putstatic     #2   // 将修改后的值存入静态变量COUNTER8: return

2.2 decrement 相关字节码

public static void decrement();Code:0: getstatic     #2   // 获取静态变量COUNTER的值3: iconst_1           // 准备常量14: isub               // 自减5: putstatic     #2   // 将修改后的值存入静态变量COUNTER8: return

2.3 图示出现各种结果的原因

Java 的内存模型如下,完成静态变量的自增、自减需要在主存和工作内存中进行数据交换:

2.3.1 出现负数的情况

2.3.2 出现正数的情况

3. 解决方案 

3. 1 临界区

一个程序运行多个线程本身是没有问题的,问题出在多个线程访问共享资源,多个线程读共享资源其实也没有问题,在多个线程对共享资源读写操作时发生指令交错,就会出现问题。一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区

3. 2 竞态条件

多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件

3.3 解决方案

为了避免临界区的竞态条件发生,有多种手段可以达到目的

  • 阻塞式的解决方案:synchronized,Lock
  • 非阻塞式的解决方案:原子变量

本篇博文以 synchronized 关键字来演示

3.3.1 修改 increment、decrement 方法
@Slf4j(topic = "c.Sync01")
public class Sync01 {private static int COUNTER = 0;public synchronized static void increment() {COUNTER++;}public synchronized static void decrement() {COUNTER--;}public static void main(String[] args) throws Exception {Thread t1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {increment();}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {decrement();}}, "t2");t1.start();t2.start();t1.join();t2.join();log.info("COUNTER = {}", COUNTER);}}

这时候不管运行多少次,COUNTER 的值都为 0

3.4 图示方法添加 synchronized 关键字后的流程图

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

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

相关文章

一次渲染十万条数据:前端技术优化(上)

今天看了一篇文章&#xff0c;写的是一次性渲染十万条数据的方法&#xff0c;本文内容是对这篇文章的学习总结&#xff0c;以及知识点补充。 在现代Web应用中&#xff0c;前端经常需要处理大量的数据展示&#xff0c;例如用户评论、商品列表等。直接渲染大量数据会导致浏览器性…

【C++登堂入室】类和对象(下)

目录 一、 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit关键字 二、static成员 2.1 概念 2.2 特性 三、友元函数 3.1 友元函数 3.2 友元类 四、内部类 五、 再次理解类和对象 结尾 一、 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xf…

【C++】多态的认识和理解

个人主页 文章目录 ⭐一、多态的概念&#x1f384;二、多态的定义及实现1.多态的构成2.实现多态的条件3.虚函数的概念4.虚函数的重写和覆盖5.析构函数的重写6.协变7.override和 final关键字8.重载、重写/覆盖、隐藏这三者的区别 &#x1f3e0;三、纯虚函数和抽象类的关系&#…

三目运算及简单案例

//三目运算是用来简化判断的 //所谓的三目 有三个表达式组成 //表达式一 条件表达式 返回的结果是布尔 //表达式二 条件表达式结果为true 时 返回的结果 //表达式三 条件表达式结果为false 时 返回的值 int age 20; //获取用…

树莓派驱动之spi回环测试

开启spi sudo raspi-config选择Interfacing options,选择spi打开 lsmod可以看到spi_bcm2835 短接MISO和MOSI 编写回环代码spitest.c #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h>…

【Python机器学习】NLP信息提取——命名实体与关系

我们希望计算机能够从文本中提取信息和事实&#xff0c;从而略微理解用户所说的内容。例如&#xff0c;当用户说“提醒我星期一浏览***.org网站”&#xff0c;我们希望这句话触发当天后下一个周一的日程或者提醒的操作。 要触发上述操作&#xff0c;需要知道“我”代表一种特定…

【devops】devops-gitlab之部署与日常使用

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

新任项目经理,如何快速接手项目

新任项目经理踏上管理岗位&#xff0c;面临着前所未有的挑战与机遇。如何快速适应角色&#xff0c;有效管理团队&#xff0c;确保项目顺利推进&#xff0c;是每一位新任项目经理必须面对的。 一、深入了解项目与团队 1、项目定位与规划 新任项目经理应对项目进行全面的调研与…

初识zookeeper

Zookeeper介绍 Zookeeper是Apache Hadoop项目下的一个子项目&#xff0c;是一个树形目录服务。 Zookeeper是一个分布式的、开源的分布式应用程序的协调服务。 Zookeeper提供的主要功能包括&#xff1a; 配置管理分布式锁集群管理 Zookeeper数据模型 Zookeeper客户端常用命…

windows使用tcpdump.exe工具进行抓包教程

windows主机安装一些抓包工具可能有些不方便&#xff0c;这里有一个tcpdump.exe工具直接免安装&#xff0c;可以直接使用进行抓包。&#xff08;工具下载见 附件&#xff09; tcpdump.exe使用教程 如下&#xff1a; 1&#xff1a;tcpdump -D 可查看网络适配器(注意前面的编号)…

分治算法专题(一)——快速排序之【三路划分】

目录 1、分治算法简介 2、算法应用【leetcode】 2.1 题一&#xff1a;颜色分类 2.1.1 算法原理 2.2.1 算法代码 2.2 题二&#xff1a;排序数组——数组分三块原理 2.2.1 算法原理 2.2.2 算法代码 2.3 题三&#xff1a;数组中的第K个最大元素 2.3.1 算法原理 2.3.2 算…

各大平台统遭入侵??区块链市场遭攻击损失近3亿!

今年&#xff0c;全球发生多起骇人听闻的勒索入侵软件攻击事件&#xff0c;黑客组织利用各种手段和技术&#xff0c;不断试图突破网络安全防线&#xff0c;窃取敏感信息、破坏系统运行&#xff0c;甚至进行勒索和敲诈&#xff0c;使得网络安全问题日益凸显其重要性和紧迫性。 S…

Mysql分组取最新一条记录

文章目录 Mysql分组取最新一条记录1. 数据准备1. 方法1&#xff1a;使用子查询获取每个组的最大时间戳&#xff0c;然后再次查询获取具体记录&#xff08;如果时间戳是唯一的&#xff09;2. 方法2&#xff1a;使用窗口函数&#xff08;MySQL 8.0&#xff09;3. 方法3&#xff1…

TikTok跨境电商营销新策略:品牌联盟与影响力经济的结合

随着TikTok成为全球化的社交和电商平台&#xff0c;也给跨境卖家提供了新的商机。境电商通过与其他知名品牌、网红或KOC建立品牌联盟&#xff0c;能够有效实现资源共享、优势互补&#xff0c;并推动市场扩张&#xff0c;带来更大的商业价值和品牌影响力。本文Nox聚星将和大家探…

鸿蒙开发协调布局CollapsibleLayout

鸿蒙开发协调布局CollapsibleLayout 首先鸿蒙我暂时没找到官方提供的协调布局&#xff0c;所以得自己自定义。 一、思路 可滚动头部、粘性头部、可滚动内容布局 可折叠区域高度可滚动头部高度-粘性头部高度 二、效果图 鸿蒙开发协调布局CollapsibleLayout 三、关键代码 //…

优思学院|如何从零开始自己学习六西格玛?

优思学院为学习六西格玛管理的学员&#xff0c;精心推荐了几本由浅入深、系统全面的书籍&#xff0c;帮助大家从入门到精通&#xff0c;逐步掌握六西格玛这一强大的管理工具。无论你是刚接触六西格玛的初学者&#xff0c;还是想在专业领域提升的高级学员&#xff0c;这几本书都…

【ARM】Trustzone和安全架构

Trustzone的基本概念&背景和历史 什么是Trustzone&#xff1f; 什么是TEE&#xff1f; Trustzone是一个技术&#xff0c;是一个技术的设计&#xff0c;一个安全架构&#xff0c;既不是软件也不是硬件。 TEE (Trusted Execution Environment) 可信执行环境。就是依托Trust…

速响低代码平台:升级营销管理系统,开启高效无忧新体验!

当前日新月异的商业环境&#xff0c;企业面临着前所未有的挑战与机遇。随着市场竞争的日益加剧和企业业务的不断拓展&#xff0c;传统的营销方式和管理手段逐渐显露出其局限性&#xff0c;难以适应快速变化的市场需求。 数据收集难&#xff1a;传统的营销管理缺乏对客户数据的收…

战神诸神黄昏9月19日登录PC端! 手机怎么玩战神诸神黄昏

9月19日&#xff0c;《战神&#xff1a;诸神黄昏》正式登录PC端&#xff0c;这是一部动作冒险游戏。要是你想随时随地在手机或平板上也能玩《战神&#xff1a;诸神黄昏》&#xff0c;可以使用网易GameViewer远程帮你实现。 网易GameViewer远程作为一款专为游戏玩家打造的远程软…

轻松让U盘数据恢复的教程:一步步指导,快速找回丢失文件

在日常使用U盘的过程中&#xff0c;我们可能会不小心删除或格式化了一些重要文件&#xff0c;导致数据丢失。面对这种情况&#xff0c;很多人可能会感到焦虑和无助。但其实&#xff0c;只要掌握了正确的方法&#xff0c;U盘数据的恢复并不复杂。本文将为大家提供一份详细的教程…