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关键字就代表着

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

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

相关文章

存储或读取时转换JSON数据

一、 数据库类型 二、使用Hutool工具 存储时将数据转换为JSON数据 获取时将JSON数据转换为对象 发现问题&#xff1a; 原本数据对象是Address 和 Firend但是转换完成后数据变成了JSONArray和JSONObject 三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器 package …

STL速查

容器 (Containers) 图解容器 支持随机访问 stringarrayvectordeque支持支持支持支持 string 类 构造函数 string(); ------创建一个空的字符串 例如: string str;string(const char* s); ------使用字符串s初始化string(const string& str); ------拷贝构造 赋值操作…

Android GPU渲染屏幕绘制显示基础概念(1)

Android GPU渲染屏幕绘制显示基础概念&#xff08;1&#xff09; Android中的图像生产者OpenGL&#xff0c;Skia&#xff0c;Vulkan将绘制的数据存放在图像缓冲区中&#xff0c;Android中的图像消费SurfaceFlinger从图像缓冲区将数据取出&#xff0c;进行加工及合成。 Surface…

OpenMVS学习笔记(一):WSL编译安装测试

1.CUDA和CUDNN安装 [1] WSL版本cuda安装&#xff1a; >> wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin >> sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600 >> wg…

7个AI驱动的3D模型生成器

老子云AI生成3D模型https://www.laozicloud.com/aiModel 在快速发展的技术世界中&#xff0c;人工智能 (AI) 已经改变了游戏规则&#xff0c;尤其是在 3D 对象生成领域。 AI 驱动的 3D 对象生成器彻底改变了我们创建和可视化 3D 模型的方式&#xff0c;使该过程更加高效、准确…

Star-CCM+通过将所有部件创建一个区域的方式分配至区域后子区域的分离,子区域材料属性的赋值,以及物理连续体的创建方法介绍

前言 上次介绍了将零部件分配至区域的方法与各个方法之间的区别&#xff0c;本文将继续上次的讲解&#xff0c;将其中的“将所有部件分配至一个区域”的应用进行补充。 如下图所示&#xff0c;按照将所有部件创建一个区域的方式分配至区域后&#xff0c;在区域下就会有一个区域…

若依集成mybatis-plus 超详细教程(亲测可用)

文章目录 简介步骤第一步第二步第三步第四步第五步第六步 使用QueryWrapperservice层impl 实现接口类层Mapper层 简介 话不多说 直接跟着下面的教程操作&#xff0c;如果有报错私信我&#xff0c;或者通过博文下面的微信名片加我微信&#xff0c;免费解答哦&#xff01; 步骤 …

opencv图片的旋转-------c++

图片的旋转 /// <summary> /// 图片的旋转 /// </summary> /// <param name"img"></param> /// <param name"angle">旋转角度:正数&#xff0c;则表示逆时针旋转;负数&#xff0c;则表示顺时针旋转</param> /// <…

【吊打面试官系列】Java高并发篇 - 什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing )?

大家好&#xff0c;我是锋哥。今天分享关于 【什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing )&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 什么是线程调度器(Thread Scheduler)和时间分片(TimeSlicing )&#xff1f; 线程调度器是一个操作系统…

2024中国植物资源化妆品创新展在国家植物园成功举办

2024中国植物资源化妆品创新展&#xff08;简称国植美妆展&#xff09;于今年05月06日在北京国家植物园圆满落下帷幕。国植美妆展由中国广告协会化妆品工作委员会与中国抗衰老促进会化妆品产业分会指导&#xff0c;北京华晟德观文化科技发展有限公司主办&#xff0c;于03月30日…

安卓模拟器访问主机局域网

误打误撞能够访问主机局域网了 但是不太懂是因为哪一部分成功的 先记录一下 PC&#xff1a;mac系统 安卓编译器&#xff1a;Android Studio 步骤 只需要在PC上进行设置 1. 在【设置】中&#xff0c;打开已连接的Wi-Fi的【详细信息】 2. TCP/IP --> 配置IPv6&#xff0c;修…

前端组件库之ant-design-vue

在这里记录一个这个组件库我之前没有发现最近才发现的一个很好用的功能&#xff08;应该叫功能吧&#xff1f;&#xff09; 就是 这个flex弹性布局&#xff0c;之前在开发时&#xff0c;一直使用elementUI,是第一次使用这个组件库&#xff0c;所以没有发现这个功能这么好用 你…

WPF控件之StackPanel布局控件

StackPanel别名堆栈panel 使其子元素按照一定方式进行布局&#xff0c;子元素排布方式要么设置为水平排布&#xff0c;要么垂直排布。 属性 Orientation设置排列方式(默认的是垂直排布) : Horizontal水平排布 Vertical 垂直排布 实例 <StackPanel Orientation"Vert…

视频号小店怎么做?店铺运营详细步骤讲解,全网独家

大家好&#xff0c;我是电商笨笨熊 视频号小店作为今年的电商黑马&#xff0c;下一个站在风口的项目&#xff0c;自是吸引了不少的玩家&#xff1b; 先不说视频号自身庞大的流量体系&#xff0c;单单是高客单的市场就值得尝试一把&#xff1b; 且当前视频号小店刚刚推出不久…

智慧文旅赋能旅游服务升级:以科技创新驱动行业变革,打造智慧化、个性化、高效化的旅游新体验,满足游客日益增长的多元化需求

目录 一、引言 二、智慧文旅的概念与内涵 三、智慧文旅在旅游服务升级中的应用 1、智慧旅游服务平台建设 2、智慧景区管理 3、智慧旅游营销 四、智慧文旅推动旅游行业变革的案例分析 案例一&#xff1a;某智慧旅游城市建设项目 案例二&#xff1a;某景区智慧化改造项目…

Redis简介和数据结构

目录 简介 进入之后身份认证才能使用 优点 用途&#xff1a; 数据结构 string string自动扩容 Redis中的简单动态字符串&#xff08;SDS&#xff09;具有以下优点&#xff1a; SDS数据的编码格式 比较&#xff1a; string 常用操作 分布式锁 使用情况&#xff0c;…

Dark Reader:夜间模式,启动!

名人说&#xff1a;一点浩然气&#xff0c;千里快哉风。 ——苏轼 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、介绍二、下载安装1、Chrome应用商店&#xff08;需科学&#xff09;2、第三方直链下载 三、使…

Pygame简单入门教程(绘制Rect、控制移动、碰撞检测、Github项目源代码)

Pygame简明教程 引言&#xff1a;本教程中的源码已上传个人Github: GItHub链接 视频教程推荐&#xff1a;YouTube教程–有点过于简单了 官方文档推荐&#xff1a;虽然写的一般&#xff0c;但还是推荐&#xff01; Navigator~ Pygame简明教程安装pygame一、代码框架二、案件输入…

五一开始内卷前端,如何迅速的一个月内找到工作!

写在前面 五一过了代表新的一年不知不觉过了半年了&#xff0c;各位工作找到怎么样&#xff0c;有没有在工作中遇到解决不了的问题&#xff0c;这些问题后面怎么处理了呢&#xff1f; hello大家好&#xff0c;我又又又来了&#xff0c;今天纯干货&#xff0c;上班的朋友适当摸…

Linux下的I2C通信

I2C通信: 一.硬件初识: IIC(inter-intergrated-Circu):内部集成总线 四线通讯:SCL,SDA,GND,VCC,串行,半双工 I2C 总线是同步,串行,半双工通信总线。 I2C 总线由时钟线 SDA 和 SCL 两根信号线构成。并且都有上拉电阻。确保总线空闲状态为高电平。 I2C 总线支持多…