【多线程】多线程(4)(线程安全问题的原因,如何解决线程安全问题)

news2024/11/18 5:46:30

【线程安全问题的原因(重点掌握)】

1.线程在操作系统中:随机调度,抢占式执行(核心原因)

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

3.修改操作「不是原子的」

4.内存可见性

5.指令重排列

(后两个原因后面再谈)

对于多线程(3)末尾两个线程对count++的修改操作来说,它「不是原子的」,不是原子的修改操作会产生线程安全问题

“原子”是不可分割的最小单位

站在cpu的视角上,「一条指令」就是cpu不可分割的最小单位,因此它在进行调度切换线程时,势必会确保:执行完这条指令再进行调度切换

因此前文中“count++”这种操作就「不是原子的」,因为它背后包含了三个指令

【如何解决线程安全问题】

最主要的办法,就是把「非原子的代码」打包成「原子的代码」,也被称为「加锁」

通过这种加锁的方式,放在前文count++的代码中,就可以令一个线程在执行count++的过程中,其他线程不能count++进来

【synchronized使用方式一:圆括号指定锁对象】

synchronized是完成“加锁”操作的关键字

「synchronized」是一个关键字,不是函数,后面的“()”并非是参数,里面需要指定一个“锁对象”,来表示对谁加锁,后面的大括号中存放的就是要打包成原子操作的代码

 public static int count = 0;
    public static Object locker = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() ->{
            for(int i = 0;i < 50000;i++){
                synchronized (locker) {
                    count++;
                }
            }
        });
        Thread t2 = new Thread(() ->{
            for(int i = 0;i < 50000;i++){
                synchronized (locker) {
                    count++;
                }
            }
        });

        t1.start();
        t2.start();
        t2.join();
        t2.join();
        System.out.println("count=" + count);

锁对象可以通过如图所示,通过Object类来创建,在synchronized的()中就可以存放这个锁对象

在进入代码块时,就会针对锁对象加锁

在出了代码块时(包括return,抛出异常),针对锁对象解锁

synchronized的{}中还可以放任意的其他代码,包括调用其他方法之类,只要是合法的代码皆可以

因此,在该代码中,由于t1和t2都是针对locker进行加锁,t1先加锁,因此t1加锁成功,并执行锁内部的代码,t2后加锁,发现locker对象被t1已经使用了,因此t2加锁失败,进入阻塞,一直阻塞到t1释放锁为止

【加锁的有效性】

上述代码有效的前提是,两个线程都加锁,且都加同一把锁

若有线程不“加锁”:

若针对不同的对象“加锁”:

锁对象,就是用来区分两个/多个线程是否针对“同一个对象”加锁

若是,则会出现「阻塞」(锁竞争/锁冲突),若不是,则不会出现阻塞,两个线程仍然是随机调度的并发执行

因此,锁对象,填哪个对象不重要,重要的是,多个线程是否针对同一个锁对象

【锁对象的类型】

锁对象,必须是一个对象

不能用int,double这种内置类型来写,锁对象的类型必须是Object类或它的子类

也就是说,用String,List<>这种类型构建锁对象是完全可以的

此外,若是多个线程(两个以上)针对同一个锁对象加锁,拿到锁的对象释放了锁后,剩下的线程谁先拿到锁?这是随机的

【synchronized使用方法二:修饰一个静态的方法】

相当于针对“对应的类对象”加锁(这里设该代码在Counter类中)

这个「文件名.class」的写法就是「类对象」

一个Java进程中,一个类的类对象是只有一个的,类对象也是对象,所以也能写到synchronized中,写类对象和写其他对象没有任何本质区别

换句话说,写成类对象就是“偷懒”的做法,不想创建单独的锁对象,就可以用类对象来客串一下

【synchronized使用方法三:修饰一个普通的方法】

相当于针对this加锁

public class Demo3 {
    public static int count = 0;
    synchronized public void add() {
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
        Demo3 demo3 = new Demo3();//创建类对象的实例
        Thread t1 = new Thread(() ->{
            for(int i = 0;i < 50000;i++){
               demo3.add();
            }
        });
        Thread t2 = new Thread(() ->{
            for(int i = 0;i < 50000;i++){
                demo3.add();
            }
        });

        t1.start();
        t2.start();
        t2.join();
        t2.join();
        System.out.println("count=" + count);


    }
}

调用方法时并没有直接写synchronized,但方法本身带有synchronized,这样的方法也是可以起到加锁的效果

synchronized需要明确锁对象,针对于这个写法,锁对象就是“this”

★总结

锁,需要的时候才能使用,不需要的时候不要使用,因为会付出代价(性能)

使用锁,就可能触发阻塞,一旦某个线程阻塞,啥时候能恢复阻塞,从而继续执行,就不可预期了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2176208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多元函数微分学基础题

这是基础题&#xff01;&#xff01;原则上必须要在第一轮初学并做完课后习题之后再做这个基础题&#xff0c;不能有错误&#xff08;马虎大意除外&#xff09;或无法解答。如有错误&#xff0c;该单元需要重学&#xff01;&#xff01; 多元函数微分学填空题 一、填空题 如…

基于SPI协议的Flash驱动控制

1、理论知识 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;通讯协议&#xff0c;是Motorola公司提出的一种同步串行接口技术&#xff0c;是一种高速、全双工、同步通信总线&#xff0c;在芯片中只占用四根管脚用来控制及数据传输&#…

关于Fake Location定位,运动世界校园问题

不好意思&#xff0c;之前那个文章其实是很早之前的&#xff0c;不知道为什么审核了很久一直没有通过&#xff0c;然后前几周莫名其妙点了一下重新发布&#xff0c;竟然发布成功了&#xff0c;这个方法已经失效了&#xff0c;要可以稳定&#xff0c;我建议是买一台root的手机&a…

Element-Plus中上传文件upload取消提示按钮与文字

去除提示按钮与文字 添加样式&#xff0c;让这个div进行隐藏 .el-upload__input {display: none !important; }

单片机长短按简单实现

单片机长短按简单实现 目录 单片机长短按简单实现1 原理2 示例代码2.1 按键实现 3 测试log4 其他实现方式 1 原理 按键检测和处理的步骤如下&#xff1a; 1&#xff1a;定时扫描按键&#xff08;使用定时器定时扫描&#xff0c;也可以用软件延时或者系统心跳之类的方式&#…

【动态规划-分组背包】力扣1981. 最小化目标值与所选元素的差

给你一个大小为 m x n 的整数矩阵 mat 和一个整数 target 。 从矩阵的 每一行 中选择一个整数&#xff0c;你的目标是 最小化 所有选中元素之 和 与目标值 target 的 绝对差 。 返回 最小的绝对差 。 a 和 b 两数字的 绝对差 是 a - b 的绝对值。 示例 1&#xff1a; 输入…

DAY17||654.最大二叉树 |617.合并二叉树 |700.二叉搜索树中的搜索 |

654.最大二叉树 题目&#xff1a;654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树…

物联网系统中TFT_LCD屏主流驱动方案详解

01 物联网系统中为什么要使用TFT-LCD驱动芯片 在物联网系统中使用TFT-LCD&#xff08;薄膜晶体管液晶显示器&#xff09;驱动芯片的原因主要可以归纳为以下几点&#xff1a; 专业性与高效性 1、专业图形处理&#xff1a;TFT-LCD驱动芯片内置了专业的图形处理引擎&#xff0…

全功能运营级开源跨境电商平台源码 —— 多语言全球化商城解决方案

实测分享【全功能运营级开源跨境电商平台】&#xff0c;它不仅默认集成了中英文双语系统&#xff0c;更内置了强大的翻译接口&#xff0c;支持自动翻译至全球133种语言&#xff0c;为商家打开通往世界的窗口。 核心特性亮点解析&#xff1a; 多语言自动翻译&#xff1a;该平台…

WEB 编程:富文本编辑器 Quill 配合 Pico.css 样式被影响的问题之还是 iframe

这个系列已经写了 3 篇了。这篇写如何使用 iframe 解决标题里面提到的问题。 前情提要 请看上一篇博文&#xff1a; WEB 编程&#xff1a;富文本编辑器 Quill 配合 Pico.css 样式被影响的问题之Shadow DOM WEB 编程&#xff1a;富文本编辑器 Quill 配合 Pico.css 样式被影响…

常见字符函数和字符串函数(上)

1. 字符分类函数 字符分类函数是一类用于判断字符是否属于特定的字符类别&#xff08;如字母、数字、标点符号等&#xff09;的函数。在C语言中&#xff0c;这些函数通常可以在<ctype.h>头文件中找到&#xff0c;它们对于文本处理和输入验证非常有用。 这些函数通常返回…

Windows系统镜像下载

目前官网还可以下载的系统有Win10和Win11&#xff0c;Win7因为已经停止维护&#xff0c;所以只能到第三方镜像站下载&#xff0c;下面将具体展示下载方法。 Win7 下载地址&#xff1a;MSDN, 我告诉你 - 做一个安静的工具站 在操作系统中找到Windows 7&#xff0c;在右侧选择…

Python | Leetcode Python题解之第445题两数相加II

题目&#xff1a; 题解&#xff1a; class Solution:def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:if head is None or head.next is None:return headnew_head self.reverseList(head.next)head.next.next head # 把下一个节点指向自己head…

魔都千丝冥缘——软件终端架构思维———未来之窗行业应用跨平台架构

一、创生-魔都千丝冥缘 在那神秘而复杂的数字世界里&#xff0c;软件的舞台上正上演着一场精彩的剧目。当面对终端单页面中如蛛网般交织的复杂业务逻辑&#xff0c;我们如同在迷雾中摸索前行。多个表单承载着各自的使命&#xff0c;却又有着相同字段的微妙关联&#xff0c;而内…

【C++前缀和 动态规划 贪心】813. 最大平均值和的分组|1936

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 C动态规划 贪心(决策包容性) LeetCode813. 最大平均值和的分组 给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个非空子数组&#xff0c;且数组内…

【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术QueSearch

【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术Que2Search 目录 文章目录 【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术Que2Search目录0. 论文信息1. 研究背景&#xff1a;2. 技术背景和发展历史&#xff1a;3. 算法建模3.1 模型架构3.1.1 双塔与分类 …

物流货运托运发货单二联三联打印软件定制 佳易王物流单管理系统操作教程

一、前言 物流货运托运发货单二联三联打印软件定制 佳易王物流单管理系统操作教程 1、软件为绿色免安装版&#xff0c;解压即可使用&#xff0c;已经内置数据库&#xff0c;不需再安装。 2、软件下载可以到本文章最后点击官网卡片下。 二、软件程序教程 1、如图&#xff0c;…

C++入门(2)--引用

6.引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 类型& 引用变量名(对象名) 引用实体&#xff1b; //引用 //类型& 引用变量名(对象名) 引…

基于php的幸运舞蹈课程工作室管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

24-9-28-读书笔记(二十)-《契诃夫文集》(四)上([俄] 契诃夫 [译] 汝龙 )

文章目录 《契诃夫文集》&#xff08;四&#xff09;上&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09;目录阅读笔记记录总结 《契诃夫文集》&#xff08;四&#xff09;上&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09; 时间过得好快啊&#xff0c;马上又要十月份了&#x…