synchronized锁介绍

7 篇文章 0 订阅

本文主要介绍synchronized的锁实现。

锁的存储

Java中的每一个对象都可以作为锁。synchronized关键字分为如下三种场景:

  • 修饰普通方法时,锁住的是调用该方法的对象实例
  • 修饰静态方法时,锁住的死当前类的Class对象
  • 修饰代码块时,锁住的是括号里的配置的对象

Java对象头内部有一个Mark Word,存储着对象的hashcode、分代年龄、持有偏向锁的线程ID,锁标志位等信息。锁信息就存储在对象头。

锁的分类

锁按照级别从低到高依次是: 无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁。锁可以升级但不能降级。

几种锁对应的

锁类型最多参与竞争的线程个数最多线程竞争时各个线程状态
偏向锁1个获取锁
轻量级锁2个1个已经获取锁, 一个自旋等待
重量级锁大于等于31个已经获取锁, 其他的阻塞等待
无锁

无锁没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功。

一般使用CAS来实现。无锁在某些场景下的性能很高。

偏向锁

大部分情况下,锁不仅不存在竞争,而且是由同一个线程多次获取该锁。从而引入了偏向锁的概念。

偏向锁是指当一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,从而降低获取锁的代价。

偏向锁的获取:

  1. 当一个线程获取锁时, 会在对象头内部记录该线程的ID
  2. 当该线程退出或者重新获取锁时, 不需要使用CAS进行操作, 只需要简单判断对象头内部是否存储着该线程的ID, 若存在, 则获取锁成功。

偏向锁的释放:

偏向锁并不会自己主动撤销, 只有当有其他线程来竞争锁, 持有偏向锁的线程才会释放偏向锁,撤销之后, 将会恢复到无锁或者轻量级锁状态。

轻量级锁

当锁是偏向锁的时候,且被另外的线程所访问,此时偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。

重量级锁

在轻量级锁的状态下,若当前只有一个等待线程,则该线程通过自旋等待。但是出现以下两种情况时,轻量级锁就会升级成重量级锁,此时等待锁的线程进入都会进入阻塞状态。

  • 自旋等待线程的自旋次数超过最大值。
  • 此时出现第三个线程来竞争锁。

参考资料:

  1. https://tech.meituan.com/2018/11/15/java-lock.html
  2. 《并发编程的艺术》
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值