线程安全性问题的原因

1.抢占式执行随机调度


  这里的意思就是,当两个线程同时启动的时候,两个线程会同时进行,并且是抢占式执行的。

而且是随机调度资源的。

如代码:

public class Deome4 {

    public static void main(String[] args)  {


        Thread t1 = new Thread(()-> {

            for(int i = 0; i < 100; i++){
                try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
               System.out.println("t1线程");
            }
        });

        Thread t2 = new Thread(()-> {

            for(int i = 0; i < 100; i++){
                try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
                System.out.println("t2线程");
            }
        });

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


    }
}

如打印结果:

以上我们可以看到,线程是同时进行的。


2.两个线程同时修改同一个变量


  当两个线程同时修改一个变量时,会存在运算被覆盖的情况。

如代码:

public class Deome4 {
    private  static int count = 0;

    public static void main(String[] args) throws InterruptedException {


        Thread t1 = new Thread(()-> {
           for(int i = 0; i < 10000; i++){
               count++;
           }
        });

        Thread t2 = new Thread(()-> {
            for(int i = 0; i < 10000; i++){
                count++;
            }
        });

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

        t1.join();
        t2.join();
        System.out.println(count);
    }
}

如图:

上述代码,如果按照步骤应该是 20000, 但这里结果不是,这里就存在了问题。

主要是因为 在对 count++的时候,共分为3个步骤,因为线程的抢占式执行,导致有的值被覆盖掉了,所以不一样。


3.修改操作不是原子的


  咱们就拿 count++ 为例,

count++ 分为3个步骤:

load:把内存中的数据读取到寄存器中。

add:把寄存器中的数据加1。

save:把寄存器中的值写入到内存中。

这里的原子性就是指不可拆分。

因为这里不是原子性的,着里线程随机调度,就会中出现错误。


4.内存可见性问题

  什么是内存可见性问题呢?

如代码:

public class Deome4 {
    private  static int count = 0;

    public static void main(String[] args) throws InterruptedException {


        Thread t1 = new Thread(()-> {
            while(count == 0){

               ;

            }
            System.out.println("t1 循环结束");
        });

        Thread t2 = new Thread(()-> {
            Scanner sc = new Scanner(System.in);
            count = sc.nextInt();
        });

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

        t1.join();
        t2.join();

        System.out.println(count);
    }
}

如图:

按道理来说我如果这里输入的是1,那么代码应该就结束的,但是这里并没有结束,此时就是内存可性问题。

这里是因为,我们的load的执行速度相比于cmp慢了太多了。此时JVM就做出来一个非常大胆的决定--不再真正的去重复load了,因为判定好像没人去修改count的值,所以干脆就只获取一次就好了,此时就出现了前面运行的情况了。


以上是线程安全问题的4种原因。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024单品正价起号,直播素材投流选品,【选品课】+【投流课】+【素材课】+【卡首屏】

课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/89064168 更多资源下载&#xff1a;关注我。 课程内容: 01 01 1.如何养账号过风控,mp4 01 1.如何搭建一条计划(1)..mp4 02 1.如何搭建一条计划(2)..mp4 02 02 2.单品起号方案如何选择,mp4 03 2.-比…

【ONE·基础算法 || 字符串】

总言 主要内容&#xff1a;编程题举例&#xff0c;熟悉理解字符串类题型。       文章目录 总言1、字符串2、最长公共前缀&#xff08;easy&#xff09;2.1、题解 3、最长回文子串 (medium)3.1、题解 4、二进制求和&#xff08;easy&#xff09;&#xff1a;高精度加法4.1、…

2.网络编程-HTTP和HTTPS

目录 HTTP介绍 HTTP协议主要组成部分 GET 和 POST有什么区别 常见的 HTTP 状态码有哪些 http状态码100 HTTP1.1 和 HTTP1.0 的区别有哪些 HTTPS 和 HTTP 的区别是什么 HTTP2 和 HTTP1.1 的区别是什么 HTTP3 和 HTTP2 的区别是什么 HTTPS的请求过程 对称加密和非对称…

armlinux裸机-uart

uart是一对一的串行异步全双工通信通信协议&#xff0c;串行速度较慢&#xff08;usart支持同步通信&#xff09; 传输原理 多个参数可以设置 为满足使用需求&#xff0c;我们一般都用带fifo缓冲中断。 我们使用S3C2440芯片&#xff0c;具体寄存器操作可以查看用户手册

积木报表Excel数据量大导出慢导不出问题、大量数据导不出问题优化方案和分析解决思路(优化前一万多导出失败,优化后支持百万级跨库表导出)

文章目录 积木报表Excel数据量大导出慢导不出问题、大量数据导不出问题优化方案和分析解决思路&#xff08;优化前一万多导出失败&#xff0c;优化后支持百万级跨库表导出&#xff09;优化结果需求背景和解决方案的思考解决方案流程描述&#xff1a;关键代码引入easy excel新建…

CentOS7.9.2009安装elasticsearch7.11.1(单节点)

本文章使用CentOS7.9.2009服务器安装elasticsearch7.11.1软件 1.服务器信息 [root@elasticsearch ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [root@elasticsearch ~]# [root@elasticsearch ~]# cat /etc/hosts | grep elasticsearch 192.168.10.24…

如何理解图像处理领域的病态问题(ill-posed problem)

ill-posed problem&#xff0c;我们可以理解为病态问题或者不适定问题。在本文中&#xff0c;统一成为不适定问题。 在讨论不适定问题&#xff08;ill-posed problem&#xff09;之前&#xff0c;我们先来看一下什么叫适定性问题&#xff08;well-posed problem&#xff09;。…

14届蓝桥杯 C/C++ B组 T7 子串简写 (字符串)

采用存储目标字符下标的方法&#xff0c;此题的想法比较新奇&#xff0c;故予以记录。 存好下标之后&#xff0c;可以先定位好启始的字符&#xff0c;然后去搜结尾字符符合长度k并且最靠近启始字符的下标&#xff0c;找到之后可以直接取到这个下标之后的所有下标&#xff0c;因…

3d怎么在一块模型上开个孔---模大狮模型网

在进行3D建模时&#xff0c;有时候需要在模型上创建孔&#xff0c;以实现特定的设计需求或功能。无论是为了添加细节&#xff0c;还是为了实现功能性的要求&#xff0c;创建孔都是常见的操作之一。本文将介绍在3D模型上创建孔的几种常用方法&#xff0c;帮助您轻松实现这一目标…

免费全开源,功能强大的多连接数据库管理工具:DbGate

DbGate&#xff1a;您的全能数据库指挥中心&#xff0c;一站式免费开源解决方案&#xff0c;无缝连接并管理多款主流数据库&#xff0c;让复杂的数据世界变得轻松易控! - 精选真开源&#xff0c;释放新价值。 概览 DbGate 是跨平台的数据库管理器。支持 MySQL、PostgreSQL、SQ…

新零售SaaS架构:客户管理系统架构设计(万字图文总结)

什么是客户管理系统&#xff1f; 客户管理系统&#xff0c;也称为CRM&#xff08;Customer Relationship Management&#xff09;&#xff0c;主要目标是建立、发展和维护好客户关系。 CRM系统围绕客户全生命周期的管理&#xff0c;吸引和留存客户&#xff0c;实现缩短销售周…

chrome 浏览器 有自带的自动字幕功能,支持英文,控制您的音乐、视频等媒体内容

chrome 浏览器 有自带的自动字幕功能&#xff0c;支持英文&#xff0c;控制您的音乐、视频等媒体内容

Android Studio学习15——多页面情况下再看Activity生命周期

按返回键退出APP时&#xff1a; 走正常页面的退出流程&#xff1a;onPause–>onStop–>onDestroy(会Destroy,因为它从任务栈中退出了) 再点击图标回来时&#xff1a; 走正常页面的创建流程&#xff1a;onCreate–>onStart–>onResume 按Home键退出App时&#xff1a…

【C#】yield使用

&#x1f4bb;代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ConsoleApp15 {internal class Program{static void Main(string[] args){IEnumerable<int&…

深度比较Vue 3.0中的computed和watch属性用法与最佳实践

摘要&#xff1a;在Vue 3.0中&#xff0c;computed和watch属性是用于处理数据逻辑的重要工具。本文将详细对比这两个属性的工作原理、适用场景以及使用时的注意事项&#xff0c;旨在帮助开发者更有效地选择和使用它们。 一、computed属性 computed属性是Vue 3.0中用于计算数据…

【小白学机器学习10】假设检验之1:F检验,F检验量的构造,F分布,F分布查表求P值等

目录 1 什么是F检验 F-test 1.1 F-test的定义 1.1.1 维基百科对F检验的定义 1.1.2 百度百科的定义 1.2 F检验的别名 1.3 F检验的判断手段 / 要达成的目标 / 适用范围 1.3.1 判断手段 1.3.2 对H0原假设的理解 1.3.3 判断目标/目的 1.3.4 适用的范围&#xff0c;场合 …

C++【组合模式】

简单介绍 组合模式是一种结构型设计模式&#xff0c; 只有在可以将对象拆分为【树状结构】的情况下使用。并且像使用独立对象一样使用它们。 常用于表示与图形打交道的用户界面组件或代码的层次结构。 基础理解 Q&#xff1a;为什么要用组合模式 &#xff1f; A&#xff1a;在…

每天学习一个Linux命令之curl

每天学习一个Linux命令之curl 在Linux系统中&#xff0c;有很多有用的命令可以帮助我们与网络进行交互。一个非常常用的命令是curl&#xff0c;它是一个功能强大的工具&#xff0c;可用于发送、接收和处理各种网络请求。本文将详细介绍在Linux下使用curl命令的各种选项及其用法…

011_C标准库函数之<time.h>

头文件<time.h>中说明了一些用于处理日期和时间的类型和函数。其中的一部分函数用于处理当地时间&#xff0c;因为时区等原因&#xff0c;当地时间与日历时间可能不相同。clock_t和time_t是两个用于表示时间的算术类型&#xff0c;而struct tm则用于存放日历时间的各个成…

QT学习day1

#include "mywidget.h"myWidget::myWidget(QWidget *parent): QWidget(parent) {this->resize(645,455);//设置窗口大小this->setWindowTitle("QQ");//设置窗口标题this->setWindowIcon(QIcon("D:\\QQ\\1579398717\\FileRecv\\pictrue\\qq.p…