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

【操作系统】解析线程安全中的 Synchronized 关键字

目录

  • synchronized
    • 一、互斥性
    • 二、可重入性
    • 三、synchronized的使用

synchronized

synchronized作为确保多线程安全的重要关键字
接下来我们来学习它的特性:

  1. 互斥性
  2. 可重入性

一、互斥性

synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,其他线程如果也执行
到同⼀个对象synchronized就会阻塞等待.

  • 进入synchronized修饰的代码块,相当于加锁

  • 退出synchronized修饰的代码块,相当于解锁
    在这里插入图片描述
    synchronized⽤的锁是存在Java对象头⾥的。
    在这里插入图片描述

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

注意:

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

synchronized的底层是使⽤操作系统的mutexlock实现的.

二、可重入性

synchronized同步块对同⼀条线程来说是可重入的,不会出现自己把自己锁死的问题;

Java中的synchronized是可重入锁

for (int i = 0; i < 50000; i++) {synchronized (locker) {synchronized (locker) {count++;}}
}

在可重入锁的内部,包含了"线程持有者"和"计数器"两个信息.

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

三、synchronized的使用

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

  1. 修饰代码块:

明确指定锁哪个对象.

    1. 锁任意对象

代码如下:

public class SynchronizedDemo {private Object locker = new Object();public void method() {synchronized (locker) {}}
}
  1. 2 锁当前对象
    代码如下:
public class SynchronizedDemo {public void method() {synchronized (this) {}}
}
  1. 直接修饰普通⽅法:锁的SynchronizedDemo对象
public class SynchronizedDemo {public synchronized void methond() {}
}
  1. 修饰静态⽅法:锁的SynchronizedDemo类的对象
public class SynchronizedDemo {public synchronized static void method() {}
}

我们重点要理解,synchronized锁的是什么

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【C++】:红黑树深度剖析 --- 手撕红黑树!
  • MySQL之索引及简单运用
  • 文本编辑三巨头(grep)
  • 【Node.js基础04】node.js模块化
  • 个人电脑网络安全 之 防浏览器和端口溢出攻击 和 权限对系统的重要性
  • C++ set
  • vue3学习记录1:emit的写法
  • java8函数式编程学习(二):optional,函数式接口和并行流的学习
  • Java-根据前缀-日期-数字-生成流水号(不重复)
  • 力扣34题 双二分查找(简单易懂)
  • go语言的命名规则
  • C#中的Func
  • 探索 IPython %%sql 魔术:数据库交互的高效工具
  • git 使用教程
  • 压测实操--kafka-consumer压测方案
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 0x05 Python数据分析,Anaconda八斩刀
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • KMP算法及优化
  • mongodb--安装和初步使用教程
  • 大快搜索数据爬虫技术实例安装教学篇
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 第十八天-企业应用架构模式-基本模式
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 通过git安装npm私有模块
  • 微服务核心架构梳理
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • HanLP分词命名实体提取详解
  • postgresql行列转换函数
  • Spring Batch JSON 支持
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​插件化DPI在商用WIFI中的价值
  • ###项目技术发展史
  • (C++17) std算法之执行策略 execution
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (动态规划)5. 最长回文子串 java解决
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (转)甲方乙方——赵民谈找工作
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 连接达梦数据库开发环境部署
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • @Conditional注解详解