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

synchronized

⭐ 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖

synchronized

  • 1. 特性
    • 1.1 互斥
    • 1.2 可重入
  • 2. 使用
    • 2.1 修饰代码块
    • 2.2 修饰普通方法
    • 2.3 修饰静态方法

1. 特性

1.1 互斥

synchronized 会起到互斥效果,某个线程执⾏到某个对象的 synchronized 中时,其他线程如果也执⾏到同⼀个对象synchronized 就会阻塞等待。
在这里插入图片描述

synchronized⽤的锁是存在Java对象头⾥的。可以粗略理解成,每个对象在内存中存储的时候,都存有⼀块内存表⽰当前的 “锁定” 状态(类似于厕所的 “有⼈/⽆⼈”)。
如果当前是 “⽆⼈” 状态,那么就可以使⽤,使⽤时需要设为 “有⼈” 状态;如果当前是"有⼈"状态,那么其他⼈⽆法使⽤,只能排队。

在这里插入图片描述

针对每⼀把锁,操作系统内部都维护了⼀个等待队列。当这个锁被某个线程占有的时候,其他线程尝试进⾏加锁,就加不上了,就会阻塞等待,⼀直等到之前的线程解锁之后,由操作系统唤醒⼀个新的线程,再来获取到这个锁。

注意:

  • 当上⼀个线程解锁之后,下⼀个线程并不是⽴即就能获取到锁,⽽是要靠操作系统来 “唤醒”,这也就是操作系统线程调度的⼀部分⼯作。
  • 假设有 A B C 三个线程,线程 A 先获取到锁,然后 B 尝试获取锁,然后 C 再尝试获取锁,此时 B 和 C都在阻塞队列中排队等待。但是当 A 释放锁之后,虽然 B ⽐ C 先来的,但是 B 不⼀定就能获取到锁,⽽是和 C 重新竞争,并不遵守先来后到的规则。

1.2 可重入

synchronized 同步块对同⼀条线程来说是可重⼊的,不会出现⾃⼰把⾃⼰锁死的问题。

什么情况下,会把自己锁死?
⼀个线程没有释放锁,然后⼜尝试再次加锁。
// 第⼀次加锁,加锁成功
// 第⼆次加锁,锁已经被占⽤,阻塞等待。
按照之前对于锁的设定,第⼆次加锁的时候,就会阻塞等待。直到第⼀次的锁被释放,才能获取到第⼆个锁。
但是释放第⼀个锁也是由该线程来完成,结果这个线程已经躺平了,啥都不想⼲了,也就⽆法进⾏解锁操作。这时候就会 死锁,这样的锁也就称为 不可重入锁

在可重⼊锁的内部, 包含了 “线程持有者” 和 “计数器” 两个信息。

  • 如果某个线程加锁的时候,发现锁已经被⼈占⽤,但是恰好占⽤的正是⾃⼰,那么仍然可以继续获取到锁,并让计数器自增。
  • 解锁的时候计数器递减为 0 的时候,才真正释放锁。(才能被别的线程获取到)

2. 使用

synchronized 本质上要修改指定对象的 “对象头”。从使⽤⻆度来看,synchronized 也势必要搭配⼀个具体的对象来使⽤。

2.1 修饰代码块

明确指定锁哪个对象

//锁任意对象
public class SynchronizedDemo {private Object locker = new Object();public void method() {synchronized (locker) {}}
}
//锁当前对象
public class SynchronizedDemo {public void method() {synchronized (this) {}}
}

2.2 修饰普通方法

锁的 SynchronizedDemo 对象

public class SynchronizedDemo {public synchronized void methond() {}
}

2.3 修饰静态方法

锁的 SynchronizedDemo 类的对象

public class SynchronizedDemo {public synchronized static void method() {}
}

两个线程竞争同⼀把锁,才会产⽣阻塞等待。
两个线程分别尝试获取两把不同的锁,不会产⽣竞争。

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

相关文章:

  • Vue在页面上添加水印
  • SQL server 数据库练习题及答案(练习2)
  • minicube搭建golang容器服务
  • 图片批量处理:图片批量缩放,高效调整尺寸的技巧
  • 直接插入排序【从0-1学数据结构】
  • C++/CLI——1简介
  • C#实现串口通讯
  • NLP论文阅读记录 - 以大语言模型为参考学习总结
  • 前端---资源路径
  • 【2024考研】心情记录
  • MySQL数据库日志管理和数据的备份及恢复
  • node-schedule nodejs定时提醒(并判断段是否是工作日)
  • LeetCode 75| 前缀和
  • 智能,轻量,高效的爬虫工具 (爬虫宝第一代), HSpider
  • IDEA Maven Helper插件 解决jar冲突
  • 装饰 Web3 项目的用户交互界面(Web3项目二实战之四)
  • 【数据库系统概论】第3章-关系数据库标准语言SQL(3)
  • 理解io/nio/netty
  • 旅游品牌网站搭建的作用是什么
  • Linux操作系统——进程(五)环境变量
  • 西门子博途怎么使用PID_Compact做pid调试
  • 结构型模式 | 适配器模式
  • 基于Python的车牌识别系统实现
  • 时间序列预测模型介绍及使用经验总结
  • Docker知识总结
  • 算法训练营Day25
  • docker笔记2-docker 容器
  • redis 从0到1完整学习 (七):ZipList 数据结构
  • 2015年第四届数学建模国际赛小美赛C题科学能解决恐怖主义吗解题全过程文档及程序
  • 基于Java开发的微信约拍小程序