收藏多年的线程安全问题大全笔记(上篇)——{线程不安全的背后原理},笔记一生一起走,那些日子不再有

本篇会加入个人的所谓鱼式疯言

❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言

而是理解过并总结出来通俗易懂的大白话,

小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.

🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!

在这里插入图片描述

引言

🦊🦊🦊🦊

在并发编程的广阔世界里,有一个隐匿的陷阱,它静静地潜伏在每一个试图并行处理任务的程序之中,那就是线程安全问题。想象一下,当多个线程同时访问并修改同一块内存区域时,犹如多辆马车在狭窄的小道上竞相前行,稍有不慎便可能引发混乱与冲突。本文将带您深入探索线程安全问题的本质,揭示其背后的原理与危害,并为您铺设一条通向安全并发编程的道路。准备好,让我们一起揭开线程安全的面纱,确保您的程序在并发的浪潮中稳健前行。

🦊🦊🦊🦊

前言

在前面文章的学习中, 我们认识到了

💞 💞

  1. 并发编程认识,和对于程序本身上效率的提高。

从中也更加明白

  1. 进程本质上就是 系统资源分配 的基本单位 , 比较 量, 开销较大。

  2. 线程则是 系统调度执行 的基本单位, 比较 量, 开销较小。

试想一下,并发编程虽然较好效率较高。 但同时也会产生相关的问题 , 从而导致我们程序出现 BUG

而这些问题我们称之为 线程安全问题 , 在本篇中小编带着小伙伴认识线程安全问题, 并用相对应的方案来 解决线程安全问题

需要回顾的小伙伴可以点击下面链接学习哦

进程与线程的零基础讲解

💞 💞

目录

  1. 线程安全问题的初识

  2. 线程安全问题产生的原因

  3. 线程安全问题的解决方案

  4. 锁的使用原理和方式

一. 线程安全问题的初识

线程安全问题是什么? 🤔 🤔 🤔 🤔

1. 线程安全问题的概念

线程安全问题是当我们进行 并发编程 时,多个线程同时执行一段代码,出现 BUG 的情况。

注意我们只有在并发编程中, 才有可能会出现 实际结果预期结果 不一致的情况,而这种情况,我们就就称为 线程安全问题

故言之, 我们 一个线程执行的串行编程 就不会出现这种情况。

那么这是什么原因呢? 为什么我们的串行编程不会出现BUG , 而我们的 并发编程就会出现相关的BUG 呢?

下面就让我们继续往下看看吧 💥 💥 💥 💥

二. 线程安全问题产生的原因

在讲解线程安全问题产生的原因之前, 小编想举个栗子,只有通过 实际的栗子 才能更好的说明,更好的让小伙伴理解 线程安全 的根源。

1. 举个栗子

class  synchronousDemo2 {
   



    public  static  int count =0;
    public static void main(String[] args) throws InterruptedException {
   
        Thread t1 =  new Thread(()-> {
   
            // 给线程1 加锁

                for (int i = 0; i < 10000000; i++) {
   
                    count++;
                }


        });

        Thread t2 = new Thread(()-> {
   
            // 给线程2 加锁

                for (int i = 0; i < 10000000; i++) {
   
                    count++;
                }

        });

//        先执行线程 1
        t1.start();

        t2.start();

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


        System.out.println(count);
    }


}

在这里插入图片描述

看到上述代码,小伙伴是否就很吃惊, 为啥两个线程同时运行, 都加上 10000000 次, 所以我们得到的应该是 20000000 才对,但是实际得到的结果却是 < 20000000 的数字。

这时我们就称为出现的 BUG 了,也就出现了 线程安全问题

2. 线程安全的原因

之前的文章我们学过, 在我们计算机中, 执行一次加法,操作系统要发出一系列的指令来对CPU进行 计算操作。

而我们加法的指令整体可以简单划分为:Load , add , save 的三个指令的执行

Load: 从内存中读取数据

add: 自增数据

save: 返回数据到内存中

那么当我们进行两次相加的时候

<1>. 串行执行

在这里插入图片描述

如果是 串行执行 的话,每个指令是 完整执行 的, 而 每个指令和下一个指令 也是衔接好执行 自增操作 的, 也就是三个指令之间也是相互配合, 完成 + 1 操作 的。

<2>. 并发执行

在这里插入图片描述

虽然每个独立的指令是完整执行的,但是指令和指令之间的配合是 不完整

其原因就在并发执行的一个本质的特点:

随机调度抢占执行

本质就是 指令抢占去执行 ,从而导致 指令执行的不确定 ,造成了 自增 时, 三条配合的指令不能完全连续执行下来,导致指令和指令之间相互错综重复的执行, 造成 不可预期的BUG

鱼式疯言

思考一下:

  • 想上面的两个线程计数都累加10000000 , 如果出现线程安全问题,有没有最终的总和 可能 == < 10000000== ,答案是 完全有可能的

因为这种 线程中 随机调度,抢占执行 , 其实情况是 很复杂的, 而小编上面作的图也只是其中 一种情况 , 真正在 线程随机调度的执行 的过程中, 其实是 很复杂的过程

一句话概括:

串行执行时 有序的 ,并发执行是 随机调度,抢占执行的 ,更容易出现 BUG

竟然小伙伴们都知道知道并发执行产生BUG的原因啦,那我们该怎么解决这个问题 ???

请移步下一节观赏哦 ❣️ ❣️ ❣️ ❣️

三. 线程安全问题的解决方案

1. 方案的引入

关于线程安全问题

小编在这里还得补充产生线程安全的主要因素有哪些 :

  1. 随机调度,抢占执行 [内因]
  1. 不同的线程 针对 同一个变量 进行 修改 操作
  1. 修改操作是 非 “原子” 性 。

像上面的栗子我们已经很清楚的表明了 随机调度,

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邂逅岁月

感谢干爹的超能力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值