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

JavaEE 多线程详细讲解(2)

1.线程不安全分析

(1)线程不安全的主要原因就是,系统的抢占式执行,对于内核设计者来说,这是非常方便的一个执行方式,但是这却却导致线程不安全的问题,也有不抢占执行的系统,但是这种系统会导致你的系统性能不是特别好。

(2)多个线程执行操作一个对象不会发生线程不安全的情况

(3)String之所以设置成无法改变,也是为了线程安全,如果想改可以试一试反射 

(4)为了更好的解决线程不安全问题,我们可以将非原子操作改成原子操作这个月就可以更安全的保证线程的安全

2.锁

2.1锁的定义

(1)锁可以理解成,解锁,上锁这个操作,拿到锁以后,就可以使你的线程互斥,只有这个线程搞完然后释放锁,然后需要的线程拿到锁以后才能继续执行后序的操作。

 (2)在一个程序中可以有多把锁,只有对一个非原子事物进行加锁才会发生互斥这个情况

图解

2.2锁的简单总结

2.3锁的具体实现(代码)

(1)创建一个类型(Object)由于Object类是所有类的父类所以所有类都可以拿到以Object枷锁的锁。(这种设定是不太合理的)

在python中,以及c++中能够加锁的是非常少的。

(2)锁的格式

这个锁是同步的,同步的反义词就是独占

(3)锁的注意事项

 (4)在使用sychronized方法,进入到了大括号中,就是加锁了,当这个大括号中的运行结束以后,就会自动的解锁(其他的语言也是这样的)

2.4锁的互斥

如果两个线程对对同一个对象进行加锁就会发生互斥,对两个不同的对象进行加锁就不会发生互斥。

(1)代码(互斥)

这种情况就是两个线程同时用一把锁对线程进行加锁,这时候就会发生互斥,程序会直接终止 

(2)代码(不互斥)

用两把锁对其进行加锁这时候就可以避免互斥了

 2.5图集锁的互斥

 这个拿到锁的过程可以理解为我约会一个女生这个女生同意了这个时候女生就是被我上锁了,这时候要是其他男生来就会被阻塞,约会不了

2.6代码实例

(1)代码

package thread;class Counter {private int count = 0;synchronized public void add() {count++;}public static void func() {synchronized (Counter.class) {// ....}}public int get() {return count;}
}public class Demo20 {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Counter counter2 = new Counter();// Object locker = new Object();Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {// counter.add();counter.func();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {// counter2.add();counter2.func();}});t1.start();t2.start();t1.join();t2.join();System.out.println("count = " + counter.get());}
}

我们可以用counter这个类来进行加锁,对于java来说锁只是一个标准,只要加锁的对象是一样的就行了。

其中我们也可以用this来进行加锁,这个方法也是不错的相当于简化()直接在括号里面写一个this。

3.锁的扩展用法

(1)针对类的类对象进行加锁

(2)通过反射来拿到当作锁的类的信息并进行加锁,类似于加锁继承

其中我们要注意的就是如果在多个线程对这个func方法进行调用这时候就会发生锁竞争。 

(3)解决方式 加锁这个func中的方法,当这个锁使用这个方法的时候相当于是this这个对象在使用func中的方法的这个对象,这时候就不会发生锁的竞争。

2.5锁的嵌套 

(4)对对象加锁使用对象中的方法发生锁竞争的情况。

(5)我们也可以使用静态方法来进行加锁实现,但是我并不是很推荐

4.锁的要记住的东西

3.死锁问题的出现?

3.1小练习来判断这个代码是否有问题(可能有问题也是算的)

(1)

这种写法也会可能出现问题,两个线程可能发生的问题有,t1执行完毕了,但是t2还在执行,这时候就会变成串行执行

 (2)

这串代码乍一眼看上去是没毛病,但是其实他是有问题的,for循环中的i的值会被锁锁住,所以可能会出现下面的情况,{t1在执行的过程中,t2已经执行完毕了这时候t2的i就会把t1的i给覆盖这时候就会出现问题}

(3)特殊情况(可重入锁)

3.2synchronized为什么这么智能不会被死锁? 

(1)

   当一个线程已经获得了锁并再次请求同一个锁时,JVM不会立即释放第一个锁再重新获取。相反,它会继续持有这个锁,而不会导致阻塞。这种情况被称为重入锁。因此,即使同一个线程多次请求同一个锁,它也不会释放锁再重新获取,而是继续持有锁。

另一方面,如果一个线程尝试获取一个已经被其他线程持有的锁,那么它将被阻塞,直到锁可用。这种行为是由JVM的线程调度器和对象监视器来管理的。

3.3可重入锁的作用

可重入锁相当于保护你的这个线程的安全如果用了这个线程以外的锁就会将这个锁进行阻塞,这样可以更好的保证你的线程安全

4.死锁会出现的3个场景

(1)

(2)场景而就是有两个线程,两把不同的锁,两个线程分别需要另一个线程解锁释放的锁才能执行下一步这时候就会发生死锁

(3)第三个场景就是第二个场景的升级版本 

代码

5.小知识 

1.如果需要查看哪个线程需要哪一把锁我们可以用idea中自带的软件来查找这个线程是持有的哪一把锁。画圆圈的就是这些线程获取到的锁以及这个线程的状态是什么也可以找到。

2.死锁发生的条件必须要背下来的小知识(必须要背下来)

3.多个线程要用锁的时候只需要将所得顺序约定好然后挨个加锁就行了(大致提一下后序会详细讲解)

5.引起线程不安全的主要原因 

(1)内存的可见性是可能使得线程发生线程的不安全问题。

     接下来我会写一段代码来对这种情况来进行详细的讲解。

两个线程分别是用来读和写的,但是我们会发现输入的是0但是却没有将线程1给停止。

接下来我会用图解的形式给大家详细的讲解

(2)首先我要先给大家讲解一个东西,当一个计算机对一个数据进行读取的或者比较的时候是三个操作的。

(3)load先从内存中读取数据到cpu寄存器中

(4)cmp(比较,同时会产生跳转)条件成立的时候就会继续顺序执行,条件不成立的时候就会跳转到另一个地址上面来进行执行。

(5)其中我们要注意在循环中这种操作的速度是非常快的,短时间会出现大量的load和cmp反复执行的效果

而且load执行消耗的时间会比cmp多很多!!

多个几千倍,上万倍!!

(6)在上面代码的过程中,load的速度非常慢,执行一次load消耗的时间顶成千上万倍的load的次数

(7)另外JVM还会每次发现load的执行结果是一样的,(为空),这时候JVM就会直接把load的操作直接优化了,读取到的结果将会是空。所以这就会使得循环不会被终止(相当于裁员)

(8)其中要注意的就是IO操作注定是反复hi下的结果是不相同的,所以IO操作是不会被优化掉的,IO操作是在load然后cmp之后的操作。

4.解决方式

关键字(volatile)只要用这个关键字进行修饰就让JVM知道这一部分是不需要进行优化的。

(有些人想既然不优化的化不会发生这种事情那么,JVM干嘛要进行优化,给大家举一个简单的例子,如果进行优化了,那么这个线程将会比以前的速度快十倍多)

6.线程饿死wait关键字

我们用wait关键字就代表着

相关文章:

JavaEE 多线程详细讲解(2)

1.线程不安全分析 &#xff08;1&#xff09;线程不安全的主要原因就是&#xff0c;系统的抢占式执行&#xff0c;对于内核设计者来说&#xff0c;这是非常方便的一个执行方式&#xff0c;但是这却却导致线程不安全的问题&#xff0c;也有不抢占执行的系统&#xff0c;但是这种…...

Flask-HTTP请求、响应、上下文、进阶实验

本节主要目录如下&#xff1a; 一、请求响应循环 二、HTTP请求 2.1、请求报文 2.2、Request对象 2.3、在Flask中处理请求 2.4、请求钩子 三、HTTP响应 3.1、响应报文 3.2、在Flask中生成响应 3.3、响应格式 3.4、Cookie 3.5、session&#xff1a;安全的Cookie 四、…...

springboot 设置response和request的默认格式 驼峰或者SNAKE_CASE

springboot 设置response和request的默认格式 驼峰或者SNAKE_CASE。 我们使用默认配置的情况下&#xff0c;response和request是由jackson jason序列化和解析的&#xff0c;因此&#xff0c;我们只需要配置好jackson json的默认格式就可以。 要设置 jackson json默认的更多格式…...

VR全景技术在养老院的应用优势浅析

随着时代的快速发展&#xff0c;人口老龄化越来越严重&#xff0c;如何利用VR技术提升养老服务的质量&#xff0c;成为了社会各界关注的焦点。为养老院拍摄制作VR全景&#xff0c;不仅能够为养老院的老人子女们跨越空间限制&#xff0c;实现与家人的情感连接&#xff0c;还可以…...

[Spring Cloud] (6)gateway整体加解密

文章目录 简述整体效果后端增加配置nacos增加配置GlobalConfig 添加请求整体解密拦截器DecryptionFilter添加响应整体解密拦截器EncryptionFilter 前端请求拦截器添加整体加密逻辑请求头中添加sessionId 响应拦截器添加整体解密逻辑 简述 本文网关gateway&#xff0c;微服务&a…...

RUST编程语言入门基础2024

庄晓立&#xff0c;2024年3月。 Rust简介 A language empowering everyone to build reliable and efficient software. Rust编程语言赋能所有人开发高可靠且高性能的软件。 性能 Rust is blazingly fast and memory-efficient: with no runtime or garbage collector, it can…...

Linux进程控制——Linux进程终止

前言&#xff1a;前面了解完前面的Linux进程基础概念后&#xff0c;我们算是解决了Linux进程中的一大麻烦&#xff0c;现在我们准备更深入的了解Linux进程——Linux进程控制&#xff01; 我们主要介绍的Linux进程控制内容包括&#xff1a;进程终止&#xff0c;进程等待与替换&a…...

利用IP地址查询解决被“薅羊毛”的方法

在互联网时代&#xff0c;随着各种网络诈骗手段的不断更新和演变&#xff0c;“薅羊毛”成为了一种常见的网络犯罪行为。其中&#xff0c;利用查询IP地址进行欺诈活动已经成为一种普遍的手段。当个人或组织的IP地址被不法分子查询后&#xff0c;可能会面临虚假注册、盗取个人信…...

Tomcat7+ 弱口令 后台getshell漏洞

1 漏洞背景 Tomcat 是一个流行的开源Web应用服务器&#xff0c;用于部署和运行Java Web应用程序。Tomcat 7 版本中存在一个安全隐患&#xff0c;即默认的管理员密码可能较弱或者未被修改&#xff0c;攻击者可以利用这一漏洞登录到Tomcat的管理后台&#xff0c;并上传恶意的WAR…...

香港虚拟主机哪里可以试用?用于企业建站的

香港虚拟主机适合个人、企业建站&#xff0c;包括外贸企业网站、个人博客网站、中小企业官网等&#xff0c;那么作为新手不知道哪家香港虚拟主机好用的时候&#xff0c;该如何找到可以试用的香港虚拟主机呢&#xff1f; 香港虚拟主机也称作香港空间、香港虚拟空间&#xff0c;…...

C# 集合(四) —— Set类

总目录 C# 语法总目录 集合四 Set 1. Set 1. Set 有 HashSet 和 SortedSet&#xff0c; 它们都不包含重复元素忽略添加重复值的请求无法根据位置访问元素使用Contains方法均使用散列查找&#xff0c;所以速度快 SortedSet 按照一定顺序保存元素&#xff0c;使用红黑树实现&a…...

C#实现多线程的几种方式

前言 多线程是C#中一个重要的概念&#xff0c;多线程指的是在同一进程中同时运行多个线程的机制。多线程适用于需要提高系统并发性、吞吐量和响应速度的场景&#xff0c;可以充分利用多核处理器和系统资源&#xff0c;提高应用程序的性能和效率。 多线程常用场景 CPU 密集型任务…...

C语言—控制语句

控制语句就是用来实现对流程的选择、循环、转向和返回等控制行为。 分支语句 if语句 基本结构 if(表达式) { 语句块1&#xff1b; } else { 语句块2&#xff1b; } 执行顺序&#xff1a; 如果表达式判断成立&#xff08;即表达式为真&#xff09;&#xff0c;则执行语句块…...

三. TensorRT基础入门-ONNX注册算子的方法

目录 前言0. 简述1. 执行一下我们的python程序2.转换swin-tiny时候出现的不兼容op的例子3. 当出现导出onnx不成功的时候&#xff0c;我们需要考虑的事情4. unsupported asinh算子5. unsupported deformable conv算子总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战…...

01、什么是ip、协议、端口号知道吗?计算机网络通信的组成是什么?

声明&#xff1a;本教程不收取任何费用&#xff0c;欢迎转载&#xff0c;尊重作者劳动成果&#xff0c;不得用于商业用途&#xff0c;侵权必究&#xff01;&#xff01;&#xff01; 目录 前言 计算机网络 网络ip地址 网络协议 网络端口号 前言 最近有个项目要用到相关文章…...

答题套路2 阅读理解 说明文某个词是否能去掉

观点 回答&#xff1a;不能 解词 某个词什么意思需要解释一下 反证法 如果去掉了&#xff0c;会怎么样 总结 使用这个词体现了说明文的科学性&#xff0c;严谨性...

Pytorch图像分类模型模型实时在线验证代码

1.训练并保存自己的模型 保存的模型格式为&#xff1a;XXX.pth torch.save(model, "./weight/last.pth")if best_acc <(validation_acc / len_val):torch.save(model, "./weight/best.pth")2.转化为ONNX格式 2.1环境安装&#xff08;window10&#x…...

Java高并发场景(银行转账问题)

最近面试问到了银行转账的高并发问题&#xff0c;回答的不是很理想&#xff0c;小编整理了下&#xff0c;题目大概如下&#xff1a; 有一张银行账号表&#xff08;银行账号字段、金额字段&#xff09;&#xff0c;A账号要给B账号转账&#xff0c;A扣款&#xff0c;B收款&#x…...

TypeScript 工具类型

这些工具类型是 TypeScript 提供的强大功能&#xff0c;用于操作和转换类型。下面是每个工具类型的简要说明和示例&#xff1a; 1、Record let value: Record<string, any> { name: "", age: 0, desc: [] }; let value2: { [key: string]: any } { name: &…...

[Kotlin]创建一个私有包并使用

1.创建Kotlin测试项目 在Android Studio或其他IDE中选择“Create New Project”。选择Kotlin和Gradle作为项目类型和构建系统。指定项目名称和位置&#xff0c;完成设置。 2.创建Android Library模块 官方文档&#xff1a;创建 Android 库 | Android Studio | Android De…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...