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

JavaEE初阶Day 6:多线程(4)

目录

  • Day 6:多线程(4)
    • 1. 线程不安全的原因
    • 2. 锁
    • 3. synchronized

Day 6:多线程(4)

前序:针对Day 5结尾的count++

多线程的执行,是随机调度抢占式的执行模式,某个线程执行指令过程中,当它执行到任何一个指令的时候,都有可能被其他线程把它的CPU抢占走

实际并发执行,由于上述原因以及count++本质是CPU的三个指令,两个线程执行指令的相对顺序就可能会存在多种可能,不同的执行顺序,得到的结果就可能会存在差异

1. 线程不安全的原因

(1)线程在系统中是随即调度的抢占式执行的,这是线程不安全的罪魁祸首万恶之源

(2)当前代码中,多个线程同时修改同一个变量

(3)线程针对变量的修改操作,不是“原子”的,count++这种操作不是原子的,是包含了三个指令

(4)内存可见性问题(后续介绍)

(5)指令重排序(后续介绍)

针对上述原因进行问题解决

  • 原因(1)无法干预,属于内核设计,无法改变

  • 原因(2)是一个切入点,但是在Java中,并不普适,针对特定场景可以使用,例如String是不可变对象

    • 一个线程修改同一个变量(ok)
    • 多个线程读取同一个变量(ok)
    • 多个线程修改不同的变量(ok)

    String为不可变对象:很好的保证线程安全;有稳定的哈希值;方便在常量池中缓存

  • 原因(3)是解决线程安全问题最普适的方案,可以通过一些操作,把“非原子”操作,打包成一个“原子”操作,例如:加锁

    如果某个代码操作,对应到一个CPU指令,就是原子的,对应到多个就不是原子的,每个代码最终变成哪些指令,需要对芯片手册(CPU指令集)要有比较深入的理解

2. 锁

:本质上是操作系统提供的功能,内核提供的功能,同过api给应用程序了,Java(JVM)对于这样的系统api又进行了封装(其他的语言,同样也可以封装/调用这样的系统api来完成加锁操作)

锁的操作主要是两个方面

  • 加锁:t1加锁之后,t2也尝试加锁,就会阻塞等待(系统内核控制的),在Java中就能看到BLOCKED状态
  • 解锁:直到t1解锁之后,t2才有可能拿到锁(加锁成功),体现了锁的互斥

锁的主要特性:互斥,一个线程获取到锁之后,另一个线程也尝试加这个锁,就会阻塞等待,也叫做锁竞争/锁冲突

代码中可以创建多个锁,只有多个线程竞争同一把锁,才会产生互斥,针对不同的锁,则不会

3. synchronized

synchronized (locker){.......
}
  • synchronizedJava中的关键字,指的是同步的,此处谈到的同步,指的是互斥/独占,反义词可以理解为共享
  • synchronized (locker),()里面就是写的“锁对象”
    • 锁对象的用途,有且只有一个,就是用来区分两个线程是否是针对同一个对象加锁,如果是,就会出现锁竞争/锁冲突/锁互斥,就会引起阻塞等待
    • 和对象具体是什么类型,有什么属性或者方法,没有任何关系
  • {}进入到代码块,就是给上述()锁对象进行了加锁操作,当出了代码块,就是给上述()锁对象进行了解锁操作
package thread;public class Demo20 {private static int count = 0;public static void main(String[] args) throws InterruptedException {Object locker = new Object();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();t1.join();t2.join();System.out.println("count = " + count);}
}

这两个线程中,每次进行count++是存在锁竞争的,会变成串行执行,但是执行for循环中的条件以及i++,仍然是并发执行的

package thread;class Counter {private int count = 0;//synchronized修饰普通方法,就相当于针对this加锁了public void add() {synchronized (this){count++;}}//上述方法也可以写成如下形式synchronized public void add() {count++;}public int get(){return count;}//synchronized修饰static方法,相当于针对该类的类对象加锁public static void func() {synchronized(Counter.class){//.....}}//上述方法也可以写成如下形式synchronized public static void func(){//......}}
public class Demo20 {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();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++) {counter.add();//counter.func();}});t1.start();t2.start();t1.join();t2.join();System.out.println("count = " + counter.get());}
}

synchronized(Counter.class)中的Counter.class反射,即程序运行时,能够拿到类一些属性信息,包括不限于

  • 类的名字,继承自哪个类,实现了哪些interface
  • 类提供了哪些方法,每个方法叫什么,每个方法有什么参数,参数是什么类型
  • 类提供了哪些属性,每个属性叫什么,每个属性是什么类型(public/private…)

上述信息,最初都是程序员自己写的.java源代码中提供的

  • java编译之后,.java形成了.class字节码,上述信息转化为二进制
  • java运行.class字节码,就会读取这里的内容, 加载到内存中,给后续使用这个类,提供基础
  • 所以JVM中在内存里保存上述信息的对象,就是类对象,后续想创建这个类的实例,就需要依照上述信息
  • 在Java中可以通过类名.class来拿到这个类对象,一个java进程中,某个类,只能有唯一一个类对象

所以,一旦多个线程调用func,则这些线程都会触发锁竞争

相关文章:

JavaEE初阶Day 6:多线程(4)

目录 Day 6&#xff1a;多线程&#xff08;4&#xff09;1. 线程不安全的原因2. 锁3. synchronized Day 6&#xff1a;多线程&#xff08;4&#xff09; 前序&#xff1a;针对Day 5结尾的count 多线程的执行&#xff0c;是随机调度抢占式的执行模式&#xff0c;某个线程执行指…...

微信小程序 django+nodejs电影院票务售票选座系统324kd

小程序Android端运行软件 微信开发者工具/hbuiderx uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 前端&#xff1a;HTML5,CSS3 VUE 后端&#xff1a;java(springbootssm)/python(flaskdja…...

基于springboot实现桂林旅游景点导游平台管理系统【项目源码+论文说明】计算机毕业设计

基于springboot实现桂林旅游景点导游平台管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了桂林旅游景点导游平台的开发全过程。通过分析桂林旅游景点导游平台管理的不足&#xff0c;创建了一个计算…...

idea 开发serlvet汽车租赁管理系统idea开发sqlserver数据库web结构计算机java编程layUI框架开发

一、源码特点 idea开发 java servlet 汽车租赁管理系统是一套完善的web设计系统sqlserver数据库 系统采用serlvetdaobean mvc 模式开发&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 java se…...

Unity之PUN实现多人联机射击游戏的优化(Section 3)

目录 &#x1f4a3;一、准备工作 &#x1f4a3;二、生成弹头脚本的编写 &#x1f4a3;三、实现发射和伤害同步 手雷都加了在给狗剩加个火箭筒不过分吧。效果看GIF动图&#xff0c;分别是单机和联机的效果。 添加火箭筒依旧是在原有的基础上更改&#xff0c;我查看火箭筒模型…...

PDF锐化

PDF Shaper Ultimate(pdf转图片) 编辑->添加文件->选中一个要处理的pdf 操作->转换->PDF转为图片 ComicEnhancerPro设置(把图片锐化) PDF Shaper Ultimate(图片转pdf) 编辑-添加图片->选中所有锐化处理后的图片 转换->图片转为pdf&#xff08;会把所有图…...

【python和java】

如何理解java和python的不同&#xff0c;在java中&#xff0c;先有类&#xff0c;类生出对象&#xff0c;对象承载数据。而python是直接数据&#xff0c;没有类的概念 理解 Java 和 Python 在面向对象编程&#xff08;OOP&#xff09;方面的不同&#xff0c;关键在于理解它们各…...

C盘满了怎么办,清理工具TreeSize

TreeSize是一款强大的磁盘空间分析工具&#xff0c;它可以帮助用户轻松地找出电脑中占用空间最多的文件和程序&#xff0c;从而让用户进行针对性地删除或卸载。 占用空间很小 下载链接&#xff1a;https://pan.quark.cn/s/bea23ed6b1d3...

【vue】watch 侦听器

watch&#xff1a;可监听值的变化&#xff0c;旧值和新值 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…...

校招生如何准备软件测试、测试开发岗位的面试?

校招生如何准备软件测试、测试开发岗位的面试&#xff1f; 求职建议 大家都很困惑如何学习测试&#xff1f;如何准备测试方面的面试&#xff1f; 我有朋友是做研发的&#xff0c;他认为测试不用准备&#xff0c;直接用开发的简历就行。也有人认为要学习一些测试理论&#xf…...

蓝桥杯抱佛脚篇~

文章目录 基础语法输入输出集合(set&#xff09;排序 基础语法 输入输出 # 输入一个数 nint(input())# 输入两、三个数&#xff0c;例如&#xff1a;1 2 或者 1 2 3 x,y map(int,input().split())# 输入数组 # ——— 1 —— nums[int(i) for i in input().split()] print(n…...

基于springboot的大学城水电管理系统源码数据库

基于springboot的大学城水电管理系统源码数据库 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了大学城水电管理系统的开发全过程。通过分析大学城水电管理系统管理的不足&#xff0c;创建了一个计算机管理大学城水…...

AI大模型探索之路-应用篇2:Langchain框架ModelIO模块—数据交互的秘密武器

目录 前言 一、概述 二、Model 三、Prompt 五、Output Parsers 总结 前言 随着人工智能技术的不断进步&#xff0c;大模型的应用场景越来越广泛。LangChain框架作为一个创新的解决方案&#xff0c;专为处理大型语言模型的输入输出而设计。其中&#xff0c;Model IO&#…...

【SSH】群晖开启ssh访问

群晖开启ssh访问 假设 你需要设置群晖 账号 test-user 开启ssh访问 设置 你的 test-user 为管理员权限 否则你无法通过cmd 面板 连接访问 群晖你需要哪个账号 就使用哪个账号终端 cmd连接 否则需要考虑后续创建 rsa 公密钥文件的 所属权 问题账号密码连接登录终端 ssh -p 端…...

Vue 移动端(H5)项目怎么实现页面缓存(即列表页面进入详情返回后列表页面缓存且还原页面滚动条位置)keep-alive缓存及清除keep-alive缓存

一、需求 产品要求&#xff1a;Vue移动端项目进入列表页&#xff0c;列表页需要刷新&#xff0c;而从详情页返回列表页&#xff0c;列表页则需要缓存并且还原页面滚动条位置 二、实现思路 1、使用Vue中的keep-alive组件&#xff0c;keep-alive提供了路由缓存功能 2、因为我项…...

【MVCC】深入浅出彻底理解MVCC

MVCC概述 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;即多版本并发控制。主要是为了提高数据库的并发性能而提供的&#xff0c;采用了不加锁的方式处理读-写并发冲突&#xff0c;确保了任何时刻的读操作都是非阻塞的。只需要很小的开销&#xff0c;就可以…...

【问题解决】ubuntu安装新版vscode报code-insiders相关错误

问题 目前 vscode官网 最新的包为 insiders_1.89.0-1712297812_amd64.deb &#xff0c;双击或者使用sudo dpkg -i code-insiders_1.89.0-1712297812_amd64.deb安装后报错&#xff0c;执行其他命令也报错。 安装环境&#xff1a;ubuntu18.04 dpkg: 处理软件包 code-insiders (…...

【Python】面向对象(专版提升2)

面向对象 1. 概述1.1面向过程1.2 面向对象 2. 类和对象2.1 语法2.1.1 定义类2.1.2 实例化对象 2.2 实例成员2.2.1 实例变量2.2.2 实例方法2.2.3 跨类调用 3. 三大特征3.1 封装3.1.1 数据角度3.1.2 行为角度3.1.3 案例:信息管理系统3.1.3.1 需求3.1.3.2 分析3.1.3.3 设计 3.2 继…...

Vscode设置滚轮进行字体大小的调节

Vscode设置滚轮进行字体大小的调节 正常的话按 ctrl 或者 ctrl - 进行字体的大小调节 1.打开Vscode&#xff0c;找打设置的图标&#xff0c;在点击设置&#xff0c;或者直接使用快捷键&#xff0c;【ctrl ,】 2. 在搜索框搜索Font Ligatures 3.双击进入settings.json ,找到如…...

【QT入门】Qt自定义控件与样式设计之控件提升与自定义控件

【QT入门】Qt自定义控件与样式设计之控件提升与自定义控件 往期回顾 【QT入门】Qt自定义控件与样式设计之QProgressBar用法及qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QSlider用法及qss-CSDN博客 【QT入门】Qt自定义控件与样式设计之qss的加载方式-CSDN博客 一、最终…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...