多线程3(线程安全问题及解决方案)

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

2.解决方法


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

问题引入:当两个线程同时对变量count同时各自++50000次

正常来说,得到的结果应该为10_0000,但实际得到的结果有出入

因为++这个操作在操作系统执行的过程中分为三条指令:load,add,save

这三条指令他们不是原子性的,两个线程每次执行++操作,由于CPU的调度是随机的,指不定线程1还没执行完一个完整的++操作,CPU就调度了线程2,那么就会产生指令不连续,也就是被插队的情况,从而导致不能加到10_0000,那么这就叫线程安全问题

总结原因有以下几条:

(1)随机调度

(2)多线程同时修改同一成员变量

(3)修改操作不是原子的

(4)内存可见性(不讲)

(5)指令重排序(不讲)


2.解决方法

针对上述问题,我们目前只能对原因(3)下手

解决修改操作不是原子的问题

采用加锁,把修改的这个三条指令捆绑为一个完整的指令,不允许中途被人插队

synchronized(加锁)

使用synchronized时要对同一个同一个对象进行加锁

这样才能产生锁竞争:线程1获取到锁,线程2此刻也想获取锁就得阻塞等待,线程1实现了防止被线程2插队,直到线程1释放锁才能获取到锁

情况1:一个线程加锁另外一个线程不加锁 就相当于追妹子挖墙脚

情况2:加锁位置的不同,这样锁的粒度也会不同

什么叫锁的粒度:锁内的代码逻辑复杂度与锁粒度成正比

问题:为什么synchronized的作用范围是{},其他语言则采用lock()->unlock()的方式

Java的加锁确保了锁内的操作能完整的执行完毕且**释放锁,**而lock加unlock的方式弊端在于要采用unlock手动释放锁,那么就不靠谱,可能代码执行的过程逻辑出错,或者程序员忘记手动释放锁,那么就会出现问题:占着茅坑不拉shit

加锁是有开销的:加锁的代价就是效率降低,所以不得不加锁的时候才加锁,平时能不加锁就不加锁


相关推荐
折哥的程序人生 · 物流技术专研6 小时前
第4篇:Lambda 简化策略模式(Java 8+)
java·设计模式·策略模式·函数式编程·lambda·代码简化·扩充系列
researcher-Jiang7 小时前
高性能计算之OpenMP——超算习堂学习1
android·java·学习
西门吹-禅8 小时前
java springboot N+1问题
java·开发语言·spring boot
DLYSB_9 小时前
生命通道:如何用 HIS 医疗系统直连网络声光终端,打造“零延误”的危急值响应网关?
java·网络·数据库·报警灯
skywalk81639 小时前
设计并实现段言的 C FFI 绑定机制 @Trae
c语言·开发语言·python·编程
weixin_BYSJ19879 小时前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
AI小码9 小时前
LLM 应用的缓存工程:当每次 API 调用都在燃烧成本
java·人工智能·spring·计算机·llm·编程·api
Hui Baby10 小时前
Spring Security
java·后端·spring
IT笔记10 小时前
【Rust】Rust Match 模式匹配详解
java·开发语言·rust
2zcode10 小时前
免费开源项目文档:基于MATLAB卷积神经网络的口罩佩戴检测系统
开发语言·matlab·cnn