本篇会加入个人的所谓鱼式疯言
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
引言
🦊🦊🦊🦊
在并发编程的广阔世界里,有一个隐匿的陷阱,它静静地潜伏在每一个试图并行处理任务的程序之中,那就是线程安全问题。想象一下,当多个线程同时访问并修改同一块内存区域时,犹如多辆马车在狭窄的小道上竞相前行,稍有不慎便可能引发混乱与冲突。本文将带您深入探索线程安全问题的本质,揭示其背后的原理与危害,并为您铺设一条通向安全并发编程的道路。准备好,让我们一起揭开线程安全的面纱,确保您的程序在并发的浪潮中稳健前行。
🦊🦊🦊🦊
前言
在前面文章的学习中, 我们认识到了
💞 💞
- 并发编程认识,和对于程序本身上效率的提高。
从中也更加明白
-
进程本质上就是 系统资源分配 的基本单位 , 比较
重
量, 开销较大。 -
线程则是 系统调度执行 的基本单位, 比较
轻
量, 开销较小。
试想一下,并发编程虽然较好
,效率较高
。 但同时也会产生相关的问题 , 从而导致我们程序出现 BUG
。
而这些问题我们称之为 线程安全问题
, 在本篇中小编带着小伙伴认识线程安全问题, 并用相对应的方案来 解决线程安全问题 。
需要回顾的小伙伴可以点击下面链接学习哦
💞 💞
目录
-
线程安全问题的初识
-
线程安全问题产生的原因
-
线程安全问题的解决方案
-
锁的使用原理和方式
一. 线程安全问题的初识
线程安全问题是什么? 🤔 🤔 🤔 🤔
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. 方案的引入
关于线程安全问题
小编在这里还得补充产生线程安全的主要因素有哪些 :
随机调度,抢占执行
[内因]
- 不同的线程 针对
同一个变量
进行 修改 操作
- 修改操作是 非 “原子” 性 。
像上面的栗子我们已经很清楚的表明了 随机调度,