Java Lock

本文深入探讨了Java中的锁机制,包括synchronized关键字的实现原理及其四种锁状态:无锁、偏向锁、轻量级锁和重量级锁。此外,还介绍了原子操作的实现方式以及不同类型的锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java Lock

1. synchronized的实现原理与应用

synchronized是Java元老级锁,又被称为重量级锁,JDK1.6中为了减少获得锁和释放锁带来的性能消耗而引入偏向锁轻量级锁

1.1 synchronized实现同步

synchronized实现同步的基础:java 中的每一个对象都可以作为锁,这些锁被称为内置锁或者监视锁

  • 对于普通同步方法,锁是当前实例对象
  • 对于静态同步方法,锁是当前类的Class对象
  • 对于同步方法块,锁是Synchronized括号里配置的对象

synchronized用的锁存在Java对象头里,如果对象是数组类型,则虚拟机用3个字宽存储对象头,如果对象是非数组类型,则用两个字宽存储对象头

1.2 锁的状态

JDK1.6中,锁一共有四种状态,级别从低到高依次是:

graph LR
无锁状态-->偏向锁状态
偏向锁状态-->轻量级锁状态
轻量级锁状态-->重量级锁状态

锁可以升级但是不可以降级,目的是为了提高锁和释放锁的效率

加锁方式解锁方式优点缺点使用场景
偏向锁简单地测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距如果线程间存在锁竞争,会带来额外的锁撤销消耗适用于只有一个线程访问同步块的场景
轻量级锁CAS会使用原子的CAS操作将Displaced Mark Word替换回到对象头竞争的线程不会阻塞,提高了程序的响应速度如果始终得不到锁竞争的线程,使用自旋会消耗CPU追求响应时间,同步块执行速度非常快
重量级锁线程竞争不使用自旋,不会消耗CPU线程阻塞,响应时间缓慢追求吞吐量,同步块执行速度较长

2.原子操作的实现

  • 总线锁保证原子性
    所谓总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。
  • 缓存锁定来保证原子性
    在同一时刻,我们只需保证对某个内存地址
    的操作是原子性即可,但总线锁定把CPU和内存之间的通信锁住了,这使得锁定期间,其他处
    理器不能操作其他内存地址的数据,所以总线锁定的开销比较大,目前处理器在某些场合下
    使用缓存锁定代替总线锁定来进行优化。

3.锁的类型

  1. 自旋锁
    阻塞的线程不断尝试获取锁
  2. 公平锁
    锁具有公平性,即获取锁的顺序与阻塞的顺序一致
  3. 独占锁
    某个线程获取锁后,其他线程必须等待其释放锁
  4. 共享锁
    CountDownLatch为例,锁释放时,所有在此线程上阻塞的线程都能运行

    读写锁为例,多个线程可以进行读操作,但是只有一个线程可以进行写操作(读共享)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值