汉力建设网站,企业管理工具,网站前置审批,沂源网站设计线程安全是多线程的重点和难点。
线程安全概念
线程安全#xff1a;在多线程的各种随机调度顺序下#xff0c;代码没有bug#xff0c;都能够符合预期的方式来执行#xff0c;此时认为线程安全
线程不安全#xff1a;如果在多线程随机调度下代码出现bug#xff0c;此时…线程安全是多线程的重点和难点。
线程安全概念
线程安全在多线程的各种随机调度顺序下代码没有bug都能够符合预期的方式来执行此时认为线程安全
线程不安全如果在多线程随机调度下代码出现bug此时就认为是线程不安全。
当然产生的**“bug”**算不算一个bug取决于产品的需求文档
通过一段典型的代码来认识线程不安全 预期结果count 10000 实际结果 同时每次结果不同。 上诉问题是怎么出现的 原因 Count类里面的increas方法进行的count操作在计算机底层是三条指令在CPU上完成的 1把内存的数据读取到CPU寄存器中 load 2把CPU的寄存器的值进行 1 add 3把寄存器的值写回到内存中 save 由于当前线程是两个线程修改一个变量由于每次修改是3个步骤不是原子的由于线程之间的调度顺序是不确定。“ 因此两个线程在真正执行这些操作的时候就可能有多种执行的排列顺序。
正常情况 两次累加得到的结果应该是2 出现线程不安全情况两次累加得到的结果不是2 当然看图可能理解的不好接来就选择一种情况来分析 在形如这样的排列顺序下此时多线程自增就会存在“线程安全问题” 整个线程 调度过程中执行的顺序都是随机的 由于在调度过程中出现“串行执行”两种情况的次数和其他情况的次数不确定因此得到的结果就是不确定的。串行执行正常情况那张图的两种方式就叫做串行执行 线程不安全的五种原因
1、抢占式执行罪魁祸首
多个线程调度的执行过程是随机的
多线程编程难点在编写多线程的代码的时候就需要考虑到任意一种调度的情况下都是能够运行出正确的结果的。
2、多个线程同时修改同一个变量
一个线程修改一个变量没事多个线程读同一个变量没事多个线程修改不同变量仍然没事。 这里涉及到一个面试题String是不可变对象这样设计有什么好处 1、不可变对象本质是因为private隐藏了set系列方法 2、好处线程安全是好处之一 3、修改操作不是原子的
解决线程安全问题最常见的办法就是从原子性入手把多个线程通过特殊手段打包成一个原子操作。 像count这种指令本质上是三个CPU指令 load add save CPU执行指令都是以“一个指令”为单位进行执行。 一个指令就相当于CPU上的**“最小单位”**不能说指令执行一般就把线程调度走了
但是修改操作比如int a 3这样的赋值操作就是单个CPU指令。这个时候就是更安全点。
一个代码是否线程安全判定是复杂的
4、内存可见性
JVM代码优化带来的BUG
假设我们的代码很挫目前有一个任务是上级领导让我们加4个同事微信并且问他们工作完成了没有
假设我们写的代码是这样的加一个同事等待同事同意好友回复以后再去加下一个同事问我们工作完成没有挨个问这4个。
JVM看到我们这么搓的代码上来就改成了一次性加4个同事好友等待他们回复即可。
JVM的出发点是好的但是有的时候优化过猛例如下面的代码 执行的结果 输入一个数字以后count应该是改变的可是循环没有中断仍然继续这件事JVM优化的体现 原因JVM让认为读操作非常频繁在t2线程没有输入时候t1线程一直在进行读操作但是t1没有任何改变JVM就认为重复在内存中读是冗余的直接从已经读过的缓存中拿。 5、指令重排序也是由JVM优化引起
具体在解决线程安全时候讲解