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

synchronized的特性

1.互斥

对于synchronized修饰的方法及代码块不同线程想同时进行访问就会互斥。

就比如synchronized修饰代码块时,一个线程进入该代码块就会进行“加锁”。

退出代码块时会进行“解锁”。

当其他线程想要访问被加锁的代码块时,就会阻塞等待

阻塞等待:

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

这就好比在公共厕所上厕所一个人进去之后把门关上并加锁,其他人就不能进来要在外面等待,等到里面的人把锁打开出来之后,大家才能共同竞争,而且这个等待过程是不按顺序的,就是你先来的话,这个打开的时候也不一定是你先进入这个厕所,也就是因为是抢占式执行的原因。

还有:

上⼀个线程解锁之后, 下⼀个线程并不是⽴即就能获取到锁. ⽽是要靠操作系统来 "唤醒". 这也就是操作系统线程调度的⼀部分⼯作

只有在上完厕所的人大喊一声“我上完了,你们可以进来了”,别人才能进来,而不是把门打开之后别人就立马进去 。

同样当synchronized对方法进行修饰的时候也是像代码块一样,

并且都把锁对象的信息储存在该对象的对象头中

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

 2.可重入

 synchronized修饰的代码有可重入的特性,不会发生“死锁”。

死锁:

自己已经完成加锁工作了,这个锁已经处于被占用的状态了,自己却想要再次进行二次加锁,但是由于前项规定这个锁只能由他自己释放,这个锁没有被释放,无法加锁,导致死锁。

Java 中的 synchronized 是 可重⼊锁, 因此没有上⾯的问题

在可重入锁的内部记录锁的持有者计数器的信息

如果这个对象在一次加锁之后,在一次加锁之后计数器由零变成一,此时还想进行二次加锁就会先判断这个锁的持有者是不是自己,如果是自己的话就允许再次加锁,并将计数器中的数字改成二,表示着加了两次锁。

如果要释放锁的话就会将计数器中的数字一直减到零才释放,此时才能被别的线程捕获到。

3.内存可见性

从结果上看,synchronized解决了内存可见性的问题,因为强制要求在锁释放后才能被其他线程感知调用,结果上实现了内存可见性。 


http://www.kler.cn/a/430135.html

相关文章:

  • kubeneters-循序渐进Cilium网络(二)
  • SpringBoot日常:集成Kafka
  • (长期更新)《零基础入门 ArcGIS(ArcScene) 》实验七----城市三维建模与分析(超超超详细!!!)
  • 如何在Windows上编译OpenCV4.7.0
  • asio中strand用于串行执行task
  • 【前端系列01】优化axios响应拦截器
  • 零基础微信小程序开发——小程序的宿主环境(保姆级教程+超详细)
  • 【日常记录-Git】git fetch
  • 河南师范大学在线评测系统(HTUOJ)正式上线啦!!!
  • 基于Pyhton的人脸识别(Python 3.12+face_recognition库)
  • ragflow连ollama时出现的Bug
  • Charts 教程:创建交互式图表的基础
  • 面试经典150题刷题——双指针部分
  • java+ssm+mysql房屋租赁管理系统
  • 页面置换算法模拟 最近最久未使用(LRU)算法
  • 数据结构第一弹-平衡树
  • leetcode_LCP 07
  • 现代C++ 21 any
  • 《筑牢网络安全防线:守护数字时代的生命线》
  • 阿里云ack部署rabbitmq集群
  • 网络原理之 TCP 协议
  • 启动hbase后没有hmaster进程
  • 二一(GIT4)、echarts(地图)、黑马就业数据平台(学生页-增 删 改)
  • 【论文阅读】Fifty Years of the ISCA: A Data-Driven Retrospective
  • 什么是厄尔米特(Hermitian)矩阵?
  • PHP:将数据传递给Grid++Report模板进行打印