当前位置: 首页 > news >正文

线程安全问题的原因和解决方案

原因

1.根本原因:线程的调度和执行是随机的(抢占式执行)

2.多个线程同时修改同一个变量

        ·多线程读取都没事

        ·多线程修改不同变量也没事

3.修改操作不是原子的

        补充:原子

        ·是不可拆分的最小单位

        ·在cpu执行指令的角度,执行一条指令这个做法就是原子的如果是一条指令,对于cpu来说要么就是执行完要么就是不执行,不会执行一半。

        ·=这个做法也是原子的。

        ·如果是count++这种对应了多条指令,就有可能cpu在执行过程中就执行一般,就调度走执行别人的指令,这样就不是原子的。

4.内存可见性

5.指令重排序

(主要还是前三条)

解决方案

·把修改操作变成原子的---加锁---打包成整体来达到整体性。

加锁:

synchronized (locker) {
//将操作放进锁里for (int i = 0; i < 10000; i++) {count++;}}

1.括号里放的是锁对象,要记得用之前先定义 

public static  Object locker=new Object();

2.object是锁对象的类型,取决于锁里面的东西是什么类型 

        eg:count++操作,count是int类型,要用object类型(或者用integer)

3.在加锁中,竞争同一把锁的时候才会产生“阻塞”---就看锁对象是不是同一个。

·如果是两个线程一个加锁一个没加那也不会阻塞

·两个线程都锁了而且是同一个对象才会产生锁竞争

import javax.swing.plaf.BorderUIResource;
//实现10000+10000正确显示20000
//注意解除优化volatile还有对里面的操作加锁
public class Demo1 {public static volatile int count=0;public static  Object locker=new Object();public static void main(String[] args) throws InterruptedException {Thread thread1=new Thread(()->{for (int i = 0; i < 10000; i++) {synchronized (locker) {count++;}}});Thread thread2=new Thread(()->{for (int i = 0; i < 10000; i++) {synchronized (locker) {count++;}}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println(count);}
}

·在10000+10000=20000的例子里面加锁就是要用同一个对象locker对内容count加锁,而且是二者的count都要加锁才行

        ·在++的过程里包含load-add-save-unlock

        ·t1加锁后t2的加锁不成功,阻塞等待,直到t1执行unlock释放锁

        ·t1加锁后:lock-load-add-save-unlock 从而t2执行的load到的数据就是t1已经save过的

import javax.swing.plaf.BorderUIResource;
//实现10000+10000正确显示20000
//注意解除优化volatile还有对里面的操作加锁
public class Demo1 {public static volatile int count=0;public static  Object locker=new Object();public static void main(String[] args) throws InterruptedException {Thread thread1=new Thread(()->{synchronized (locker) {for (int i = 0; i < 10000; i++) {count++;}}});Thread thread2=new Thread(()->{synchronized (locker) {for (int i = 0; i < 10000; i++) {count++;}}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println(count);}
}

        ·而对count加锁的方法除了直接锁count++之外还可以在for循环外加(这种方法是两个想你换串行的)t1不停执行循环,直到执行完10000次

        ·这两种方法中第一种比较好,便于充分利用cpu多核心资源;t1和t2谁拿到锁是不确定的。

        ·第二种没有把多核心利用起来

相关文章:

  • pikachu靶场通关笔记08 XSS关卡04-DOM型XSS
  • pikachu靶场通关笔记07 XSS关卡03-存储型XSS
  • GitCode镜像门法律分析:PL协议在中国的司法实践
  • 告别RAG上下文丢失:Late Chunking 与 Contextual Retrieval 深度对比解析
  • 路由器、网关和光猫三种设备有啥区别?
  • 【图像处理基石】立体匹配的经典算法有哪些?
  • HTML实战项目:高考加油和中考加油
  • 《Map 到底适合用哪个?HashMap、TreeMap、LinkedHashMap 对比实战》
  • 笔记思考法
  • Spring AI 之对话记忆(Chat Memory)
  • OpenCV计算机视觉实战(9)——阈值化技术详解
  • vue3 + WebSocket + Node 搭建前后端分离项目 开箱即用
  • 电机控制选 STM32 还是 DSP?技术选型背后的现实博弈
  • 【深度学习】12. VIT与GPT 模型与语言生成:从 GPT-1 到 GPT4
  • Java集合操作常见错误与最佳实践
  • 尝鲜纯血鸿蒙,华为国际版本暂时不支持升级。如mateX6 国际版?为什么不支持?什么时候支持?
  • NISCO里境全新VALUE系列合肥首店启幕,携手正反设计打造0压生活空间
  • 【无标题】C++23新特性:支持打印volatile指针
  • SQL进阶之旅 Day 7:视图与存储过程入门
  • 宝塔面板部署python web项目详细教程
  • 如何做购物网站的后台/品牌互动营销案例
  • 视频源网站怎么做/全国疫情防控最新数据
  • 扬州市邗江区建设局网站/推广网络广告
  • wordpress gitbook/seo优化师培训
  • 汽车网站设计论文/360网站推广登录
  • 动态网站的建设及综合设计/个人能接广告联盟吗