java的锁 学习笔记

对于synchronized锁

实现方式

其锁类型和状态是直接存储在java对象头的Mark Word中,锁状态的数据同步是通过JMM中的内存屏障来进行原子操作,其加锁和解锁过程直接通过底层的指令级和JVM操作对应的java对象头来实现的,且完全写死,无法对加锁和解锁过程进行自定义。

历史变化

在过去,synchronized一直是重量级锁,但是在java SE 1.6后,对该锁进行了很多优化,引入了偏向锁和轻量级锁,并建立了自动升级机制。
锁可以升级但是不能降级,目前锁有四种等级,这四种锁是针对synchronized的,不适用于Lock类型的锁。
无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁
jvm会根据竞争情况对锁进行升级。

偏向锁

适用情况:只有一个线程经获取用该锁,其他线程很少获取该锁。
处理方式:(底层过于复杂,这里用抽象的方式去描述)

  1. 线程获取该锁时直接将该锁的钥匙交给其,释放锁时不归还钥匙。之后该线程在获取该锁时只用检查钥匙即可,不再进行获取锁和释放锁的操作。
  2. 第二个线程获取该锁时,锁发现自己没有钥匙,就会将程序暂停下来。去寻找拿着钥匙的线程。
  3. 若那个线程已经不需要钥匙,则会要回钥匙并交给第二个线程。
  4. 多次执行2过程,会升级为轻量级锁。
轻量级锁

适用情况:竞争不激烈
特点:

  1. 竞争失败后通过自旋不断的获取锁。
  2. 释放锁时会判断该的竞争情况,视情况升级为重量级锁。
  3. CAS使用的也是自旋锁。
重量级锁

适用情况:竞争激烈
特点:竞争失败后线程阻塞,等待释放锁时唤醒。

对于通过实现Lock接口而建立的锁

实现方式

A -> B表示基于A实现B。

基于JMM和内存屏障的原子操作		//java底层的多线程数据同步机制
->
适用于各种不同情况的队列同步器	//这里负责实现锁状态的同步和线程的阻塞队列
->
继承Lock接口的各种不同类型的锁	//这里负责实现不同的加锁和解锁逻辑

与synchronized最大的区别就是队列同步器和Lock锁都是通过java代码实现的,可以根据需要对其进行自定义。并且这里将复杂的同步和阻塞过程都放到了同步器中,自定义新的锁时只需要考虑加锁和解锁的逻辑即可。

历史变化

在以前,java只有synchronized这一种锁,在java SE 5之后,引入了Lock接口来实现各种各样不同类型的锁。

相关概念:
  • 公平锁:按照时间顺序获取锁。
  • 排它锁:一次只能有一个线程获取。
  • 重入锁:一个线程可以n次获取该锁,同时也需要n次释放才能彻底将锁释放掉。
Lock接口各种实现:
  • ReentrantLock:重入锁,公平锁,排它锁。
  • ReentrantReadWriteLock:读写锁,重入锁,可选择是否是公平锁。
    包含一对锁,分别是读锁和写锁。支持公平性选择和锁降级(自动降级为读锁或者写锁)。

  1. 加锁的代码块过大,会降低系统的吞吐量,应尝试拆开。
  2. 加锁过多,会增加获取和释放锁的开销,应尝试合并。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值