多线程之线程安全问题

news2024/9/25 4:34:05

1.线程安全示例

class Count{
    int a = 0;
    public void add(){
        a++;
    }
}
public class ThreadDemo8 {
    public static void main(String[] args) {
        Count count = new Count();
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 5_0000; i++) {
                count.add();
            }
        });

        Thread t2 = new Thread(()->{
            for (int i = 0; i < 5_0000; i++) {
                count.add();
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(count.a);
    }
}

对于变量a是希望通过两个for循环自增到100000,但是运行结果达不到预期:

 

每一次的运行结果都是不稳定的,这就是多线程到来的问题。对上述问题进行图解(load、add、save):

对于自增操作,本质上要分为三步:

1.先把内存中的值,读取到CPU的寄存器中(load)

2.把 CPU寄存器里的数值进行+1运算(add)

3.把得到的结果写会到内存中(save)

如果是两个线程并发的执行count++,此时就相当于两组load add save进行执行.此时不同的线程调度顺序就可能会产生一些结果上的差异。

2.原因分析

线程安全问题的原因有如下:

1.根本原因:线程都是抢占式执行的,随机调度的。

2.代码结构原因:多个线程同时修改同一个变量。在有些时候,是可以通过调整代码结构来避免的。一个线程修改一个变量是没问题的,多个线程读取同一个变量也是没有问题的,多个线程修改不同的变量也是没问题的。

3.原子性:如果修改操作是原子性的,就可以避免了,比如把上述的load、add和save包装成一个整体就是ok的。针对线程安全问题,最主要的解决手段也是从原子性这个方面进行入手的。

4.内存可见性问题:如果一个线程读,一个线程修改,那么此时读取的结果可能不如预期值。

5.指令重排序:本质上是编译器优化出bug了,编译器有些时候会保证在代码逻辑不变的情况下对代码进行调整,那么有可能会把代码的执行顺序给调整了,很可能会带来问题。

3.如何解决?

用synchronized进行加锁:

进了方法就会加锁,出了方法就会解锁。如果是多个线程同时都在尝试加锁,那么最终只会有一个线程加锁成功,其他线程只能阻塞等待(BLOCKED)。加锁的本质就是把并发变成串行。加锁之后的运行结果:

4.关于synchronized的用法

1.修饰方法

修饰方法包括了修饰修饰普通方法和修饰静态方法,这两者的加锁对象是不同的。修饰普通方法,锁对象就是this;修饰静态方法,锁对象就是类对象(Count1.class)。

2.修饰代码块

修饰代码块就是手动指定锁对象。

总之,在加锁前,我们要明确执行对哪个对象加锁,如果多个线程针对同一个对象加锁,会产生阻塞等待(锁竞争/锁冲突);如果多个线程针对不同对象加锁,不会阻塞等待(不会锁冲突/锁竞争)。

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

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

相关文章

这款企业报表工具给你灵活的数据查询体验

随着对BI应用程度的加深&#xff0c;用户需要连接和管理的数据越来越多&#xff0c;也越来越复杂。电子表格软件支持丰富的数据源接入&#xff0c;但一般并不能直接使用接入的业务库直接进行数据分析。所以在报表开发前的取数过程&#xff0c;把需要的数据整合成一个数据集合&a…

Ajax技术

全局刷新和局部刷新 在B/S 结构的项目中&#xff0c; 浏览器端负责把用户的请求和参数通过网络发送给服务器,服务端负责接收请求&#xff0c;并将处理的结果返回给浏览器。浏览器端负责展示响应结果给用户。 全局刷新 整个浏览器被新的数据覆盖。在网络中传输大量的数据。浏…

经历了资本的狂热追捧之后,元宇宙开始进入到相对冷静的发展阶段里

经历了资本的狂热追捧之后&#xff0c;元宇宙开始进入到相对冷静的发展阶段里。在这样一个阶段&#xff0c;元宇宙不再被看成是一个万能的存在&#xff0c;不再被看成是一个无所不包的存在&#xff0c;而是变成了一个相对较为客观和理性的存在。看看Meta的表现&#xff0c;看看…

C#语言实例源码系列-游戏-实现俄罗斯方块

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

css新特性:线性渐变详解(重复性线性渐变、径向渐变、重复性径向渐变的使用)

线性渐变线性渐变重复性线性渐变径向渐变重复性径向渐变的使用线性渐变 线性渐变是向下、向上、向左、向右、对角方向的颜色渐变。 其语法格式为&#xff1a; background-image: linear-gradient(side-or-corner|angle, linear-color-stop);参数说明如下&#xff1a; side-o…

C++——二叉树OJ

目录 1.根据二叉树创建字符串 2.二叉树的层序遍历 3.二叉树的层序遍历2 4.二叉树的最近公共祖先 5. 搜索二叉树与双向链表 6.从前序与中序遍历构建二叉树 1.根据二叉树创建字符串 按照前序遍历&#xff1a;根左右。 1(2(4()())())(3()()) 1.左右都为空&#xff0c;则可…

通过PWM控制串行LED灯

资料下载 RGB_LED灯带_5050慢闪_datasheet STM32控制LED灯带 根据上面的说明书可知&#xff0c;通过修改800KHz的PWM波形的占空比可以控制LED的颜色。 假设现在有3颗串联起来的灯珠&#xff0c;如下图&#xff1a; 如果U1/U2/U3需要显示红/绿/蓝色&#xff0c;根据说明书&…

Vue3 的项目搭建

使用工具&#xff1a; VSCode Volar &#xff1a;编辑器和插件Vite&#xff1a;打包工具Vue3&#xff1a;VueX&#xff1a;存储NodeJs&#xff1a;环境 操作步骤&#xff1a; 安装Node.js安装VsCode安装 Volar创建一个Vite的初始化项目 npm init viteProject name 这一行 我…

Linux系统下刨析hello world背后的秘密

Hi&#xff0c;小伙伴们&#xff0c;大家好&#xff01;今天给大家讲解Linux系统编程中几个重要的概念。必须理解了这几个重要概念&#xff0c;才能更快的入门Linux系统编程&#xff0c;这是不可或缺的基础知识。看似简单&#xff0c;如果不花一番功夫很难真正的理解它们。需要…

113.(leaflet之家)leaflet根据距离截取线段

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> <html>

AAC ADTS格式分析与提取aac音频文件实战

1.AAC⾳频格式简介 AAC⾳频格式&#xff1a;Advanced Audio Coding(⾼级⾳频解码)&#xff0c;是⼀种由MPEG-4 标准定义的有损⾳频压缩格式&#xff0c;由Fraunhofer发展&#xff0c;Dolby, Sony和AT&T是主 要的贡献者。 AAC 包含两种格式&#xff1a;ADIF和ADTS 2.ADIF…

Python基础(二十):面向对象基础

文章目录 面向对象基础 一、理解面向对象 二、类和对象 1、理解类和对象

已知Retangle2的中心点坐标,角度,半长,半宽,计算四个顶点坐标和四个线段中点坐标

Halcon可以通过最小外接矩型算子获取Retangle2的中心点坐标&#xff0c;角度&#xff0c;半长&#xff0c;半宽。但是却没有四个顶点坐标和四个线段中点坐标。下面的代码是获取四个顶点坐标和四个线段中点坐标的方法。 gen_rectangle2 (Rectangle, 300, 200, 0.39, 100, 50) C…

E5071C网络分析仪

18320918653 E5071C 安捷伦E5071CAgilent 8.5G网络分析仪二手E5071C 频率范围&#xff1a;300 kHz至8.5GHz 在测试端口处保持125 dB动态范围&#xff08;典型值&#xff09; 宽动态范围&#xff1a;在测试端口上的动态范围> 123 dB&#xff08;典型值&#xff09; 极快的…

GDB调试技巧实战--找到打开某个文件的地方

问题&#xff1a; 本系列期望用一个简单的实例来展示一些调试技巧。不时更新。 本期问题是&#xff1a;如何才能快速定位到打开某个文件的代码&#xff1f;&#xff08;对应open/fopen, 读者可举一反三到其它系统函数&#xff09;。当面对屎山代码时&#xff0c;GDB的条件断点…

基于R的Bilibili视频数据建模及分析——变量相关性分析篇

基于R的Bilibili视频数据建模及分析——变量相关性分析篇 文章目录基于R的Bilibili视频数据建模及分析——变量相关性分析篇0、写在前面1、数据分析1.1 变量相关性分析1.2 单元数据直观展示1.3 多元数据直观展示2、多元数据与回归分析2.1 简单相关分析2.2 简单线性回归分析2.3 …

从0到1搭建大数据平台之调度系统

大家好&#xff0c;我是脚丫先生 (o^^o) 大数据平台核心之一在于数据计算&#xff0c;分为离线计算和实时计算任务。 然而任务是离不开调度的。比如&#xff1a;我们要进行定时抽取业务数据库 的数据&#xff0c;定时跑hive/spark任务&#xff0c;定时推送日报、月报指标数据…

数字档案馆系统测试前准备工作(“指标表”和“具体要求”可下载)

数字档案馆系统测试是国家档案局组织开展的一项针对县级以上国家综合档案馆数字档案馆建设情况的绩效评价工作。数字档案馆系统测试的评分依据是《数字档案馆系统测试指标表》&#xff08;后台回复“指标表”可下载&#xff09;&#xff0c;测试采用百分制。测试结果达到80分以…

华脉智联电力行业技术解决方案

一、前言 所谓电力应急&#xff0c;就是快速处理突发紧急事件尽量减少因供电中断造成的损失&#xff0c;快速修复故障设备或线路&#xff0c;使电力生产和运营恢复正常。重大施工事故、公共紧急事件、性质恶劣的违章操作、蓄意破坏、自然灾害等&#xff0c;都极易引发大规模停…

论文浅尝 | Future Event Prediction Based on Temporal KG Embedding

笔记整理&#xff1a;杨露露&#xff0c;天津大学硕士链接&#xff1a;https://www.techscience.com/csse/v44n3/49146/html动机对未来事件的准确预测在许多领域为社会带来巨大利益&#xff0c;减少损失&#xff0c;如内乱、流行病和犯罪。知识图谱是描述和建模复杂系统的通用语…