四、多线程带来的的⻛险-线程安全

4.1 观察线程不安全

运行以下代码:

package demo02;

public class Test {
    private static int count = 0;

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50_000; i++) {
                count++;
            }
        });

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

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

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

        System.out.println("count: " + count);
    }
}

运行之后每次的结果 count 都不一样 且不为100000

4.2 线程不安全的原因 

什么是原⼦性?

我们把⼀段代码想象成⼀个房间,每个线程就是要进⼊这个房间的⼈。如果没有任何机制保证,A进⼊ 房间之后,还没有出来;B是不是也可以进⼊房间,打断A在房间⾥的隐私。这个就是不具备原⼦性的。 那我们应该如何解决这个问题呢?是不是只要给房间加⼀把锁,A进去就把⻔锁上,其他⼈是不是就进 不来了。这样就保证了这段代码的原⼦性了。 有时也把这个现象叫做同步互斥,表⽰操作是互相排斥的。

4.2.1 对count++进行分析:

 操作系统对于线程的调度,是随机的

执行123 三个指令的时候,不一定是 一下子执行完

可能是执行到其中一部分,该线程就被调度走了

因此,线程调度是随机的 这是线程安全问题的 罪魁祸⾸

正确执行示意图:

错误执行示意图:

4.3线程不安全原因与解决小结

原因:

1.[根本原因] 操作系统上的线程是“抢占式执行”“随机调度”=>线程之间执行的顺序带来了很多变数(罪魁祸首,万恶之源)
2.代码结构.代码中多个线程,同时修改同一个变量,
              1)一个线程修改一个变量,没事的.
              2)多个线程读取同一个变量,没事的.    如果只是读取,变量的内容,固定不变的
              3)多个线程修改不同变量,没事的~~   如果是两个不同变量
                                                                          彼此之间就不会产生相互覆盖的情况了.
3.[直接原因】上述多线程修改操作,本身不是“原子的"

解决:

针对原因1,无法做出任何改变.系统内部已经实现了抢占式执行,无法干预~~
针对原因2,分情况.有的时候,代码结构可以调整,有的时候,调整不了。
针对原因3,乍看起来,count++,生成几个指令,无从干预~~但是,实际上是有办法的~~
可以通过特殊手段,把这三个指令打包到一起,成为“整体” --> 加锁 锁具有“互斥”“排他”这样的特性

4.4 解决之前的线程不安全问题

使用synchronized 进行加锁操作

public class demo01 {
    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        Object locker = new Object();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50_000; i++) {
                synchronized (locker) {
                    count++;
                }
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50_000; i++) {
                synchronized (locker) {
                    count++;
                }
            }
        });

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

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

        System.out.println("count = " + count);

    }

}

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

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

相关文章

通过Docker Compose构建自己的Java项目

通过Docker Compose构建自己的Java项目 前置条件 安装了Docker,未安装的请移步:CentOS7 / CentOS8 安装 Docker-ce安装了Docker-Compose,未安装的请移步:在CentOS7、CentOS8系统下安装Docker Compose1. 配置阿里云镜像仓库 为了提高Docker镜像的下载速度,我们可以配置阿…

版本工具报错:Error Unity Version Control

NotConfiguredClientException: Unity VCS client is not correctly configured for the current user:Client config file.

python 爬虫 入门 三、登录以及代理。

目录 一、登录 &#xff08;一&#xff09;、登录4399 1.直接使用Cookie 2.使用账号密码进行登录 可选观看内容&#xff0c;使用python对密码进行加密&#xff08;无结果代码&#xff0c;只有过程分析&#xff09; 二、代理 免费代理 后续&#xff1a;协程&#xff0c;…

TitanIDE:解锁编程教学新范式

在高校软件工程类课程教育中&#xff0c;传统编程教学方式正面临着多重痛点&#xff1a; 环境配置繁琐&#xff1a;软件工程类课程往往需要学生自行配置复杂的开发环境。但是&#xff0c;学校硬件设备条件差异、软件兼容性问题等因素&#xff0c;导致学生学习效率低下&#xf…

热销王西圣H1头戴式耳机—全平台售罄断货:揭秘抢购潮究其原因?

西圣xisem作为国内平价享轻奢的领军品牌&#xff0c;就在今年它家的头戴式蓝牙耳机性价比标杆—西圣H1&#xff0c;凭借其发烧级的千元音质、降噪与满级的旗舰配置性能&#xff0c;不仅惊艳了整个耳机圈&#xff0c;还在仅仅的几个月内&#xff0c;西圣H1头戴式耳机已经火爆断货…

python 使用gradio启动程序报错

问题一&#xff1a;localhost is not accessible 解决办法&#xff1a; export no_proxy"localhost,127.0.0.1,::1"

C#学习笔记(三)

C#学习笔记&#xff08;三&#xff09; 第 二 章 命名空间和类、数据类型、变量和代码规范二、类的组成和使用分析1. 基本概念2. 类的内容组成3. 方法的初步理解 第 二 章 命名空间和类、数据类型、变量和代码规范 二、类的组成和使用分析 1. 基本概念 类是程序的基本单元&a…

PostgreSQL中触发器递归的处理 | 翻译

许多初学者在某个时候都会陷入触发器递归的陷阱。通常&#xff0c;解决方案是完全避免递归。但对于某些用例&#xff0c;您可能必须处理触发器递归。本文将告诉您有关该主题需要了解的内容。如果您曾经被错误消息“超出堆栈深度限制”所困扰&#xff0c;那么这里就是解决方案。…

Javascript算法——二分查找

1.数组 1.1二分查找 1.搜索索引 开闭matters&#xff01;&#xff01;&#xff01;[left,right]与[left,right) /*** param {number[]} nums* param {number} target* return {number}*/ var search function(nums, target) {let left0;let rightnums.length-1;//[left,rig…

大话网络协议:从OSI七层模型说开去

时至今日,互联网已经是大家日常生活中不可或缺的一部分,购物、点餐、刷剧、网课,已经融入了我们生活的方方面面。但网络具体是怎么工作的呢? 特别是我们具体从事软件研发、ICT行业的同学,理解和掌握这个我们产品运行的基础设施尤为必要。 本文,我们会力争用最简单易懂的…

秋季猫咪疯狂掉毛,宠物空气净化器有用吗?性价比高的该怎么选?

我家猫真的是换季就变掉毛怪&#xff0c;整只猫“虚胖”了一大圈不止&#xff0c;在阳光下可以看见非常多飘在空气中的浮毛。浮毛到处乱飞&#xff0c;沉积在黑色的衣服上&#xff0c;就形成白色的薄膜。自从养猫后&#xff0c;我再也没穿过深色的衣服。 现在每天都给它梳毛&am…

Linux文件的查找和打包以及压缩

文件的查找 文件查找的用处&#xff0c;在我们需要文件但却又不知道文件在哪里的时候 文件查找存在着三种类型的查找 1、which或whereis&#xff1a;查找命令的程序文件位置 2、locate&#xff1a;也是一种文件查找&#xff0c;但是基于数据库的查找 3、find&#xff1a;针…

Vue.js 学习总结(9)—— Vue 3 组件封装技巧

1、需求说明 需求背景&#xff1a;日常开发中&#xff0c;我们经常会使用一些UI组件库诸如and design vue、element plus等辅助开发&#xff0c;提升效率。有时我们需要进行个性化封装&#xff0c;以满足在项目中大量使用的需求。错误示范&#xff1a;基于a-modal封装一个自定…

【AIGC半月报】AIGC大模型启元:2024.10(下)

【AIGC半月报】AIGC大模型启元&#xff1a;2024.10&#xff08;下&#xff09; (1) Janus&#xff08;两面神&#xff09;&#xff08;DeepSeek 1.3B多模态大模型&#xff09;(2) Stable Diffusion 3.5&#xff08;StabilityAI文生图大模型&#xff09;(3) Mochi 1&#xff08;…

Python文件操作(读取、写入、修改和删除)

目录 一、文件的读取 二、文件的写入 三、文件的修改 四、文件的删除 Python是一种功能强大的编程语言&#xff0c;文件操作是编程中常见的需求。本文将详细介绍Python中的文件操作&#xff0c;包括文件的读取、写入、修改和删除&#xff0c;帮助读者掌握Python文件操作的基…

分布式系统之异步与消息队列(MQ)(原理+代码实战一文讲清!)

异步 什么是异步 异步编程是一种编程范式&#xff0c;它允许程序在等待操作完成&#xff08;如等待网络响应、文件读写等&#xff09;时继续执行其他任务。这种编程方式对于提高程序的性能和响应性至关重要&#xff0c;尤其是在处理耗时操作或在资源受限的环境中。下面我将更…

山东以“八策并举”确保人民满意学前教育“普惠落地”

10月19日-22日&#xff0c;2024年中国学前教育研究会学术年会在山东国际会展中心召开。年会围绕“优质普惠可持续——加强学前教育高质量发展的法治保障”主题&#xff0c;通过5场主旨报告、28个园所观摩、10个分论坛交流研讨&#xff0c;为2200余名嘉宾提供智慧盛宴。成为近年…

URP学习四

一.Bilt To RTHandle feature代码&#xff1a; 二.DistortTunnel 只有个飞机却有很多太空场景。因为设置了其他pass来渲染背景 队列添加3个Pass&#xff1a; 第一个Pass把颜色图进行输出 第二个Pass&#xff1a;创建了个纹理 加了个扰动&#xff0c;把纹理进行输出 第三个pas…

Postman使用-基础篇

前言 本教程将结合业界广为推崇和使用的RestAPI设计典范Github API&#xff0c;详细介绍Postman接口测试工具的使用方法和实战技巧。 在开始这个教程之前&#xff0c;先聊一下为什么接口测试在现软件行业如此重要&#xff1f; 为什么我们要学习Postman&#xff1f; 现代软件…

电子木鱼小游戏小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 在快节奏的生活中&#xff0c;人们越来越注重内心的平静与放松。电子木鱼小游戏小程序正是基于这一需求而诞生的&#xff0c;它将传统的木鱼文化与现代科技相结合&#xff0c;为用户提供了一个简单、方便、有趣的冥想与放松工具。通过敲击屏幕上的虚拟木鱼&#xff0…