多线程的安全问题

由于多线程并发执行导致代码出现bug,就叫做线程不安全,具体的比如,新建一个thread1;

新建一个thread2;同时两个线程开始并发执行,针对变量int count=0;各自进行++5000.次;按理说得到的结果应该是100000;可使由于线程不安全导致的bug;实际上a最后的结果并不是100000;

而是小于100000的一个数,

线程安全问题是系统调度线程时候,用抢占执行的方式进行调用,某个线程什么时候上cpu执行完全不确定,如两个线程在两个cpu也可以完全并行执行,因此具体的顺序是不确定的

比如线程的工作分为1.读取,2.传到cpu上进行++,3.保存自增后的值; 

如果两个线程按照这种顺序执行那么不会产生线程安全问题,可实际上并不是这么执行的,由于线程之间的抢占执行;线程A读取要++的数为0;刚刚读取完;被b抢占完成了线程b的工作;此时b中保存的数为1;而a此时应该执行第二部工作导致自增的对象还是0;因此自增两次却只得到了一次的结果,这就导致了本来是100000的预期结果,实际上要小很多。

在极端情况下,如果每次自增都发生了线程的安全问题,那么得到的最终结果应该是50000;

如果压根没有发生线程的安全问题,那么最终的结果应该是100000;

线程不安全的原因大概总结以下五点:

1.根本原因:线程之间的抢占执行方式;线程之间里的先后顺序无法确定,这样导致结果的随机性就是根本原因

2.多个线程修改同一个变量,归根结底还是抢占执行方式的结果

(1).如果一个线程修改一个变量那么不会发生抢占,不涉及并发,结果是确定的

(2)多个线程单单读取也不会涉及安全问题

(3)多个线程修改多个变量的话,一个线程对应一个变量,也不会涉及安全问题

3.原子性

是指这个线程执行的操作是可分的,举一个简单的例子;把大象放进轿子;很明显分三个步骤;线程执行如果只有一步不会被拆解也不会涉及线程安全问题;如单单给变量赋值就是一个原子性操作。

4.内存可见性

涉及编译器的优化问题,如线程a只完成了数据的读取,此时被b抢占执行,b中对自增对象执行多次自增,那么系统会优化;提高系统的效率;不采用自增一次保存一次的方式;而是自增多次结束后直接再保存;就会出现a读取数据出现问题。

5.指令重排序

编译器会自动调整指令的顺序达到高效率的效果,可能会产生如内存可见性一样的bug

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值