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

【Java学习】锁、线程死锁、线程安全2

目录

一、对象的锁属性

1.作用

2.实现

2.1线程单代码块竞争锁

2.2锁对象判持有层信息

3.修饰

二、线程卡住

死锁

解决方法

三、线程安全2

1.不安全原因

2.措施


一、对象的锁属性

Java每个类实例对象都有的 装自带属性的 对象头内存空间里面 有锁属性

1.作用

用来锁相对代码块 调度到 相对只单线程内地 此代码块执行

2.实现

2.1线程单代码块竞争锁

一个锁对象 初始为零持有层 只能拥单线程的个代码块竞争到持有,竞争到锁 每进一层代码块 就增一层持有层信息,执行完出一层代码块 就减一层持有层,竞争到锁的代码块 可以给子代码块 可重入加层地共用

2.2锁对象判持有层信息

锁对象 用线程代码块持有层信息 为 竞争到的非零持有层线程代码块 供锁保障零持有层线程代码块 阻塞运行

3.修饰

(1)synchronized修饰静态方法,是以 类对象 为锁对象 加锁方法的整个代码块

(2)synchronized修饰非静态方法,是以 this本实例对象 为锁对象 加锁方法的整个代码块

class Counter {public int count;//increase1、2等效:synchronized public void increase1() {count++;}public void increase2() {synchronized (this) {count++;}}//increase3、4等效:synchronized public static void increase3() {}public static void increase4() {synchronized (Counter.class) {}}
}

二、线程卡住

遇阻象 找另路 地单路线搜索解决,当无另路另路循回阻象时 便卡住无法解决

死锁

锁阻象的 另路循回阻塞时 便形成了死锁

解决方法

通过删除嵌套锁的代码结构统一用锁的顺序 就可破坏掉锁请求的环路结构,解决死锁

例:线程统一先用小锁再用大锁

class Test {private static Object locker1 = new Object();private static Object locker2 = new Object();public static void main(String[] args) {Thread t1 = new Thread(() -> {synchronized (locker1) {// sleep 原先确保 t1和t2都分别拿到loker1和loker2后 再进行后续动作 发现死锁try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker2) {System.out.println("加锁成功!");}}});Thread t2 = new Thread(() -> {synchronized (/*locker2->*/locker1) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (/*locker1->*/locker2) {System.out.println("加锁成功!");}}});t1.start();t2.start();}
}

三、线程安全2

一线程读中 另线程进写时 遇到略读无感

线程安全1:多线程对同一变量写指令的互碎拆

1.不安全原因

数据读取流向

(硬盘->)内存->寄存器->cpu

读硬盘到内存 相对 读内存到寄存器 非常慢、读内存到寄存器 相对 读寄存器到cpu 又非常慢】


编译器为提高代码执行效率,在保持单线程视野 逻辑不变的前提下 调整生成 优化执行的代码内容,但在多线程下 就可能会出现 视野缺陷下带来的出错优化

在保障的单线程视野下,读取无变内存到寄存器时 可能 简化只首读不变的一次 而略去 外线程修改内存的读取

  • 主内存 是真正的定位置的内存
  • 工作内存 是不定的 存储数据的"非内存"空间,通常包括 各种cpu寄存器和缓存

2.措施

volatile确定 不会对内存略读,保障了内存的可见性

class Test {private static volatile int isQuit = 0;// volatile 确定不会对isQuit进行内存略读public static void main(String[] args) {Thread t1 = new Thread(() -> {while (isQuit == 0) {// 循环体里啥都没干,此时意味着这个循环,一秒钟就会执行很多很多次// 编译器在单线程视野内 对内存无变的isQuit 可能会 只首读不变的一次,以略读来提升效率}System.out.println("t1 退出!");});t1.start();Thread t2 = new Thread(() -> {System.out.println("请输入 isQuit: ");Scanner scanner = new Scanner(System.in);// 一旦用户输入的值不为0 就会使t1线程执行结束isQuit = scanner.nextInt();});t2.start();}
}

http://www.lryc.cn/news/622527.html

相关文章:

  • 【原理】C# 字段、属性对比及其底层实现
  • 使用npm/pnpm自身安装指定版本的pnpm
  • pnpm(Performant npm)的安装
  • Docker之安装部署——(1)配置国内docker镜像源
  • 【多模态大模型】--BLIP3
  • 疯狂星期四文案网第40天运营日记
  • PyTorch的安装-CPU版本或者GPU安装有什么区别吗
  • Comfyui进入python虚拟环境
  • 《P1194 买礼物》
  • 综合案例:Python 函数知识整合 — 学生成绩管理系统
  • 【秋招笔试】2025.08.15饿了么秋招机考-第三题
  • 无脑整合springboot2.7+nacos2.2.3+dubbo3.2.9实现远程调用及配置中心
  • hex文件结构速查
  • PyQt6实例_50个流通领域重要生产资料市场价格查看工具
  • OpenCV---getStructuringElement 结构元素获取
  • 铨林接纸机学习记录1
  • 嵌入式开发学习———Linux环境下网络编程学习(二)
  • STC8单片机驱动I2C屏幕:实现时间、日期与温湿度显示
  • AutoSar AP平台功能组并行运行原理
  • 码上爬第七题【协程+对抗格式化检测+数组移位】
  • 【Canvas与玻璃光】铝圈蓝底玻璃光按钮
  • 吉他和弦学习:从音程基石到流畅弹奏
  • 优先级反转问题
  • 在使用 scp 传输大文件时,为避免因连接超时导致传输中断
  • 领域防腐层(ACL)在遗留系统改造中的落地
  • python中的reduce函数
  • MSYS2+CMake配置C/C++开发环境
  • OpenSCA开源社区每日安全漏洞及投毒情报资讯|14th Aug. , 2025
  • plantsimulation中存储(store)、缓冲区(buffer)、放置缓冲区(PlaceBuffer)的区别,分别应用于那种情况
  • OpenCompass傻瓜式入门教程