线程的状态,多线程带来的风险,synchronized关键字及死锁问题

news2024/12/23 18:01:02

目录

状态 

线程的意义

多线程带来的风险——线程安全✅

线程安全的概念

线程不安全的原因

抢占式执行,随机性调度

修改共享数据

原子性->加🔒

可见性

指令重排序

解决线程不安全问题(学完线程再总结)

synchronized关键字——监视器锁monitor lock​编辑 

 互斥

使用示例

可重入

Java标准库中线程安全的类

死锁

1.死锁是什么

2.死锁的三个典型情况

3.死锁的四个必要条件​编辑

4.如何破除死锁?


状态是针对当前的线程调度情况进行描述的,所以认为线程是程序调度的基本单位(后面再谈状态都是考虑线程的状态了);

状态 

public class ThreadState {
    public static void main(String[] args) {
        for (Thread.State state : Thread.State.values()) {
            System.out.println(state);
       }
   }
}

1. NEW : 创建Thread对象,但是还没调用start(内核还没创建对应的PCB);

2. TERMINATED : 内核中的PCB已经创建完毕了,但是Thread对象还在;

3. RUNNABLE:可运行的;(RUNNABLE是正在CPU上执行的,RUNNING是在就绪队列上的,可以去CPU上执行的);

4. WAITING

5. TIMED_WAITING

6. BLOCKED

上述三个都是阻塞,表示线程 PCB 正在阻塞队列中,但是原因不同

RUNNABLE表示就绪状态,包含正在CPU上运行,或者在就绪队列中排队

当有for循环里有sleep的时候,t运行中的状态大部分是TIMED_WAITING, 为了让时间均衡,可以给 t 线程中添加更多的计算逻辑。

如果线程代码中全是for循环里计算,比较大小之类的操作,此时这个线程就不会阻塞,始终是RUNNABLE'状态;

所以,之前我们学过的 isAlive() 方法,可以认为是处于不是 NEW TERMINATED 的状态都是活着 的。

线程的意义

程序分成:

CPU密集:包含大量的加减乘除运算符;

IO密集:涉及到读写文件,读写控制台,读写网络的操作;

多线程可以更充分的利用到多核心cpu的资源

多线程带来的风险——线程安全✅

起源于多线程的抢占式执行带来的随机性。如果没有多线程,程序的执行顺序就是固定的;调度的源头来自于操作系统的内核实现

线程安全的概念

多个线程同时对某个共享资源进行访问导致的原子性,可见性,有序性的问题,这些问题导致共享资源存在一个不可预测性,使执行结果出现不可预期的结果。

如果多线程环境下代码运行的结果是符合我们预期的,即在单线程环境应该的结果,则说这个程序是线 程安全的。

线程不安全的原因

抢占式执行,随机性调度

修改共享数据

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

string都是不可变对象,所以他线程安全 

原子性->加🔒

 是不可拆分的基本单位,针对线程安全问题最主要的的手段就是通过加锁将非原子的转换为“原子”的,
我们把一段代码想象成一个房间,每个线程就是要进入这个房间的人。如果没有任何机制保证, A 进入 房间之后,还没有出来;B 是不是也可以进入房间,打断 A 在房间里的隐私。这个就是不具备原子性 的。
那我们应该如何解决这个问题呢?是不是只要给房间加一把锁, A 进去就把门锁上,其他人是不是就进 不来了。这样就保证了这段代码的原子性了。
有时也把这个现象叫做同步互斥,表示操作是互相排斥的。
一条 java 语句不一定是原子的,也不一定只是一条指令
比如  n++ ,其实是由三步操作组成的:
1. 从内存把数据读到 CPU
2. 进行数据更新
3. 把数据写回到 CPU
不保证原子性会给多线程带来什么问题
如果一个线程正在对一个变量操作,中途其他线程插入进来了,如果这个操作被打断了,结果就可能是 错误的。
这点也和线程的抢占式调度密切相关 . 如果线程不是 " 抢占 " , 就算没有原子性 , 也问题不大 .

可见性

 如果一个线程读,一个线程改,也可能出现问题。

指令重排序

编译器对于指令重排序的前提是 " 保持逻辑不发生变化 ". 这一点在单线程环境下比较容易判断 ,
是在多线程环境下就没那么容易了 , 多线程的代码执行复杂程度更高 , 编译器很难在编译阶段对代
码的执行效果进行预测 , 因此激进的重排序很容易导致优化后的逻辑和之前不等价 .

解决线程不安全问题(学完线程再总结)

  1. 同步代码块
  2. 同步方法

synchronized关键字——监视器锁monitor lock 

 互斥

  • 两个线程同时对一个对象进行加锁的时候,会出现锁冲突/锁竞争,一个线程可以获取到锁另一个线程出现线程阻塞的情况 ,直到那个线程解锁,它才取锁成功。
  • 两个线程,一个加锁,一个不加锁,不存在锁竞争;
  • 两个线程针对不同对象加锁,俩线程获取到各自的锁,此时不存在锁竞争;
同一个对象 synchronized 就会 阻塞等待 .
进入 synchronized 修饰的代码块 , 相当于 加锁
退出 synchronized 修饰的代码块 , 相当于 解锁
synchronized 用的锁是存在 Java 对象头里的。

 

 

使用示例

synchronized关键字

修饰方法(普通方法-加到this对象上,静态方法-加到类对象上)

代码块-手动指定加到某个对象上

 

ctrl+alt+t->选中代码块包裹 

可重入

一个线程针对同一个对象,连续加锁两次如果没有问题, 就叫可重入的,否则不可重入(第二次加锁就会出现阻塞等待的情况,这种情况线程就僵住了,出现死锁现象)。

这里的死锁(死锁的一种情况)如何理解?

灵异事件:滑稽老铁去厕所,锁上了门,结果时空错乱,它出来了,忘记了去厕所这件事,去厕所发现门一直都是锁的。

为了避免上述死锁,java将synchronized设定为可重入的。

 上述图片可以理解为:

我追到男神,追的过程中给他表白了一次,追到手后再表白了一次,就是“可重入的”,不会出现阻塞等待等。

synchronized 同步块对同一条线程来说是可重入的,不会出现自己把自己锁死的问题;

eg:

static class Counter {
    public int count = 0;
    synchronized void increase() {
        count++;
   }
    synchronized void increase2() {
        increase();
   }
}
在可重入锁的内部 , 包含了 " 线程持有者 " " 计数器 " 两个信息 .
1. 如果某个线程加锁的时候 , 发现锁已经被人占用 , 但是恰好占用的正是自己 , 那么仍然可以继续获取 到锁, 并让计数器自增 .
2. 解锁的时候计数器递减为 0 的时候 , 才真正释放锁 . ( 才能被别的线程获取)

Java标准库中线程安全的类

多个线程操作同一个集合类,就要考虑到线程安全问题。 

 

还有的类不涉及加锁,但仍然是线程安全的,因为不涉及修改操作:String; 

 

死锁

1.死锁是什么

死锁是两个或两个以上的线程在执行过程中,去争夺同一个共享资源导致的互相等待的过程,在没有外部干预的情况下,线程会一直处于阻塞状态,无法向下执行。

死锁比较隐蔽,一旦写了死锁,会出现严重的bug

2.死锁的三个典型情况

  • 一个线程,一把锁,连续锁两次,如果锁是不可重入性锁,就会死锁;Java里的synchronized和ReentrantLock都是可重入性锁;
  • 循环等待:两个线程,两把锁,t1,t2先各自针对锁A,锁B进行加锁,再尝试获取对方的锁。线程1在获取B的时候等待线程2释放B,线程2在获取A的时候等待线程1释放A,造成blocked;(线程1拿到A锁,再尝试获取锁B,A这把锁还是继续保持的,不会因为要去获取B就把A释放了)
    public class demo33 {
        public static void main(String[] args) {
            Object jiangyou=new Object();
            Object cu=new Object();
            Thread tanglaoshi=new Thread(()->{
                synchronized(jiangyou){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    synchronized (cu){
                        System.out.println("汤老师拿到了酱油和醋");
                    }
                }
            });
             Thread shiniang=new Thread(()->{
                synchronized(cu){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    synchronized (jiangyou){
                        System.out.println("师娘拿到了酱油和醋");
                    }
                }
            });
        }
    }
    //用jconsole定位到这两个线程的第二个🔒操作出现了BLOCKED操作;

     

  • 多个线程,多把锁 
    当他们都拿起左手的筷子就会出现极端情况。

3.死锁的四个必要条件

4.如何破除死锁?

去破坏死锁中的必要条件中的任意一个(除了互斥条件),给锁编号,然后制定一个固定的顺序(从小到大)来加锁,任意线程加多把锁的时候,都让线程遵循上述循序,此时循环等待自然破除。eg:对于上面的代码就可以通过把锁的内容换一下 。 

还有解决死锁的银行家算法。

对于死锁,我们需要借助jconsole这样的工具来定位。 在问到死锁时,记得再解释下可重入,不可重入

 

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

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

相关文章

使用electron套壳vue实现跨平台桌面应用

electron和vue是什么就不用多说了,前端都知道 先展示一波demo 传送门 前提条件 要有一个vue项目,老项目跳过 vue create hello-world改造vue项目 在根目录新建一个background.js文件,也可以叫其他名字,作为package.json的main…

C Primer Plus第五章编程练习答案

学完C语言之后,我就去阅读《C Primer Plus》这本经典的C语言书籍,对每一章的编程练习题都做了相关的解答,仅仅代表着我个人的解答思路,如有错误,请各位大佬帮忙点出! 1.编写一个程序,把用分钟表…

微信小程序---表格的制作并展示云数据库中的数据

微信小程序并没有表格组件,可能是官方考虑到,在前端开发中,表格的嵌套性太多,用DIV代码会比较简洁就没有实现吧。没有现成的组件可以使用,针对这个问题,目前有两种解决方案: 1)内嵌…

怎么发表CCF期刊?CCF期刊有什么不同之处? - 易智编译EaseEditing

发表CCF期刊,可以参考一下步骤: 选择目标期刊: 首先选择一个适合自己的目标期刊,可以是CCF推荐的高水平期刊,也可以是其他被广泛认可的期刊。 撰写论文: 根据目标期刊的要求,撰写论文。确保论…

「恋爱事务」NFT 作品集

「恋爱事务 (Love Affairs)」服装 NFT系列允许玩家在体验中使用 Opera Garnier 歌剧院的 T台大厅,并参与互动竞赛。参与 The Sandbox 元宇宙首个以爱情为主题的概念时装秀! 该系列已于 5 月 22 日晚上 11 点在 The Sandbox 市场平台上线。 NFT 系列介绍 …

go-zero的服务发现源码阅读

服务发现原理与grpc源码解析_wangxiaoangg的博客-CSDN博客 go-zero rpc demo官方文档:rpc编写与调用 | go-zero 目录 一 服务注册 1. 创建rpc服务 2. 启动rpc服务 3. registerEtcd做了什么 4. discov.NewPublisher 服务发布者 二 服务发现 1.定义&注册re…

如何在华为OD机试中获得满分?Java实现【差值数组不同的字符串】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

本地vue搭建的web网站项目app如何发布到互联网?

对于非专业人来说,提到 Vue并不熟悉。Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建。 简单来说,Vue是干什么用的呢?Vue通过提供了一套声明式的、组件化的编程模型,帮助你高效地开发用…

七、SpringBoot从入门到精通

一、SpringBoot概述 Spring Boot是一个基于Spring框架的开发框架,用于快速构建能够立即运行的生产级Spring应用程序。它是Spring的一个子项目,致力于使Spring开发更加简单、快速和便捷。 二、SpringBoot基础程序 1、点击Spring Initializer&#xff0…

苹果MR头显背后的秘密武器,ARKit演进历程一览

苹果MR头显可以说是板上钉钉了,看了这么多的预测,几乎没有从ARKit的角度来看苹果头显的,因此本文我们将回顾ARKit近7年来的发展历程。 实际上,ARKit 3.5开始支持LiDAR(首个搭载的设备是iPad Pro 2020)就是…

信号隔离器在水处理控制系统的应用

摘要:水处理控制系统中,其控制、监测模块的非电量模拟量传感器采用信号隔离器的接线方式合理地解决了相关模拟量传感器供电电源安全和相对独立的问题,保证了监测模块的电源、模拟量采集模块和输出模块的相对隔离,降低了可能会造成…

我想成为一名黑客

什么是黑客? 首先我们需要知道什么是黑客呢?黑客最初是指水平高超的电脑专家,而骇客就是我们常见的爱搞破坏的家伙。 黑客和骇客有什么区别呢? 如果黑客是制造炸弹的专家,那骇客就是拿着炸弹到处乱炸的坏蛋。 怎么…

如何在华为OD机试中获得满分?Java实现【合并 K 个升序链表】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

【JAVA进阶】异常处理

📃个人主页:个人主页 🔥系列专栏:JAVASE基础 目录 1.异常概述、体系 2.常见运行时异常 3.常见编译时异常 4.异常的默认处理流程 5.编译时异常的处理机制 6.运行时异常的处理机制 7.finally 8.自定义异常 1.异常概述、体系…

VUE A页面跳转到B页面带参数,且每次点击跳转,数据刷新

这里写目录标题 一、描述二、VUE带参数页面跳转跳转方式&#xff1a;1&#xff09;标签<router-link>2&#xff09;js操作跳转 三、B页面实现每次点击参数变化&#xff0c;数据刷新解决方案&#xff1a;1&#xff09;去除缓存。2&#xff09;watch监听router 背景&#x…

香港:禁止中国内地参与虚拟资产交易!散户不可交易稳定币,放开不意味着放松!

前天&#xff0c;香港证监会&#xff08;SFC&#xff09;公布了对虚拟资产交易的开放态度和监管思路&#xff0c;宣布《适用于虚拟资产交易平台营运者的指引》&#xff08;下简称《指引》&#xff09;将于2023年6月1日生效。 虽然SFC对于公众提出的建议给予了很完整的回应&…

领导下发紧急且风险大的任务,如何处理?

在遇到这种无法拒绝&#xff0c;明显很难按时交付的紧急任务时&#xff0c;项目经理处理的关键&#xff1a; 1、降低关键干系人期望值 降低关键干系人的期望值&#xff0c;是项目管理非常重要的一门艺术&#xff0c;也是让干系人满意&#xff0c;便于与关系人沟通的关键。 在项…

多地住建局推广工程资料电子化,帮助工程企业“降本增效”

工程资料签署和管理是每个在建工程绕不开的课题&#xff0c;庞大的签署量、动则几十万的签署成本如何优化&#xff1b;有关部门的合规审查如何过关…纸质工程资料需要面对的难题还有很多&#xff1a; 麻烦&#xff1a;从工程立项申报、审批、设计、施工到验收等全过程中产生的大…

7-事务

目录 1.什么是事务&#xff1f; 2.为什么用事务&#xff1f; 3.事务怎么用&#xff1f; 4.事务的四大特性&#xff08;ACID&#xff09; ①原子性&#xff08;Atomicity&#xff0c;又称不可分割性&#xff09; ②一致性&#xff08;Consistency&#xff09; ③隔离性&a…

文本转语音怎么转?教你三招轻松搞定

近年来&#xff0c;人工智能技术飞速发展&#xff0c;语音合成技术 (TTS) 已经被广泛应用于各种应用场景中。在日常生活中&#xff0c;人们经常需要阅读长篇文章、新闻报道、科技论文等&#xff0c;但传统的阅读方式不仅效率低下&#xff0c;而且容易让人感到疲劳。随着语音合成…