synchronized(锁)

synchronized:互斥锁,本质是通过锁定共享资源,达到线程安全的手段

根据使用方式,分为类锁和对象锁

修饰在静态方法,或者参数为class类的时候,都是以当前类作为共享资源进行锁定,为类锁,粒度最大。

修饰在实例方法,或者参数为指定对象实例的时候,已指定实例为共享资源进行锁定,为对象锁

 

锁的存储:对象头(MarkWord),一个对象作为锁对象,对象头会记录当前的锁状态等一些信息。

偏向锁-->轻量级锁(自旋)-->重量级锁:锁资源的抢占是阻塞的,没有获取到锁资源需要进入阻塞队列内等待唤起,但是一个锁对象并非一定是一直被占有的,所以为了提升性能,存在了锁升级

 

无锁状态-->请求线程直接获取到当前锁对象,此时对象头内记录了当前线程id,因为多数情况下,并不存在锁竞争,大概率还是当前线程来抢占锁资源的可能性最大,所以当线程再次请求,发现锁对象头内就是自身的线程id,不需要再次的加锁和释放锁,可以直接获得,不需再进入阻塞队列等待唤起。这里性能好,降低了竞争的开销

 

锁对象为偏向锁-->新的线程进行请求,发现锁对象存在非本身的线程id,为偏向锁,则通过cas对锁对象的偏向锁进行撤销,如果撤销成功,则获得锁,如果撤销失败,则将当前锁对象升级为轻量级锁,可见偏向锁只有在存在竞争的时候才会释放锁。一般撤销成功的时候,都是持有线程处在安全点的情况下,撤销锁,并不会出现线程安全问题

 

锁对象为轻量锁-->线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头的MarkWord复制到锁记录中。然后线程会尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁。如果失败,表示其他线程在竞争锁,当前线程使用自旋来获取锁。当自旋次数达到一定次数时,锁就会升级为重量级锁。

轻量级锁解锁时,会使用CAS操作将Displaced Mark Word替换回到对象头,如果成功,表示没有竞争发生。如果失败,表示当前锁存在竞争,锁已经被升级为重量级锁,则会释放锁并唤醒等待的线程。

 

重量级锁-->多个线程争抢同一个锁资源,会将抢夺失败的线程放入阻塞队列内,等待唤起,开销大,性能低

 

线程的通信(wait/notify)

就是线程的阻塞和唤起,在相同的锁对象情况下,通过线程通信切换线程状态。

盗图:

 

 

 

 

死锁:

互斥,共享资源X和Y只能被一个线程占用;

占有且等待,线程T1已经取得共享资源X,在等待共享资源Y的时候,不释放共享资源X;

不可抢占,其他线程不能强行抢占线程T1占有的资源;

循环等待,线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,就是循环等待。

 

公平锁非公平锁:非公平锁就是可以插队,公平锁FIFI无法插队

 

posted @   好好的一个居士  阅读(651)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示