JAVA多线程的初级认识4-锁的基本认识

7 篇文章 0 订阅

Java中多线程的技术必然要了解的必然是锁~锁保证多线程的数据安全。所以不多说进入主题。

最轻量级的锁Volatile

当然这是因为它只能修饰变量,而且相对于synchronized关键字轻量了很多~

对于变量增加了volatile的修饰,表示该数据的写和读都直接同步到主内存,所以保证该变量的任何修改对于其他线程是可见的。

我们可以查看关于修饰volatile变量的编译文件和指令,可以看出~里面会有一个lock的汇编指令。具体实现是通过内存屏障,具体如图:
在这里插入图片描述
同时volatile还有一个功能就是防止指令重排序。java代码到最终执行的机器码要经过几次指令排序~如下图:
在这里插入图片描述
但是volatile有些时候可能会导致误用,比如
volatile int i=0;

{
    i++;
}

这段代码再多线程的时候可能会出现问题~具体原因是i++非原子操作。可能存在覆盖的情况

synchronized

这个关键字应该很不陌生。Java 1.6之后~由于synchronized的锁太重性能很是问题,所以升级为偏向锁,轻量锁,重量锁,根据不同情况使用不同锁。

作用范围

  1. 修饰实例方法
    表示对于当前实例加锁,进入任何该对象实例修饰的代码块均需要提前获得锁。
  2. 修饰静态方法
    表示对于该类进行加锁,进入该类修饰的代码块需要获取当前类的锁。
  3. 修饰代码块
    指定加锁对象,进入加锁对象的代码块~需要提前获得该对象锁

锁的存储

由于所是锁资源对象~所以要了解一下对象在堆上的存储。一共分为三个区域对象头(header),示例数据(instanceData),和对齐填充(padding)。如图:
在这里插入图片描述
通过cpp源码可以了解到~一个对象的创建都会创建一个instanceOopDesc(数组是arrayOopDesc)在文件instanceOop.hpp里面。
在这里插入图片描述
可以看到它集成了oopDesc,而oopDesc里面包含两个成员变量(_mark,_metadata).其中_mark是markOop类型,也就是所谓的Mark World。记录了对象和锁相关的数据。

MarkWorld

markOop类型记录在markOop.hpp文件中,如下:
在这里插入图片描述
该部分记录了和锁相关的所有信息~MarkWorld具体会有5种情况:
在这里插入图片描述

锁的类型

1.6后锁的类型分为无锁,偏向锁,轻量锁,重量锁。

偏向锁

最简单的锁,支持重入,场景:经常是单线程进行锁定~即在对象_mark中通过CAS标记为偏向锁,同时将线程ID记录在对象中即可。流程如下:
在这里插入图片描述
可以通过JVM参数 UseBiasedLocking来控制是否开启。
当通过CAS失败获取偏向锁的时候,就会升级为轻量锁

轻量级锁

当偏向锁存在竞争的时候,即CAS设置偏向锁的时候失败,那么失败的线程将进行自旋操作(自旋锁)。自旋锁即采用for循环,不断的去进行获取锁的操作,所以针对同步代码块执行快的操作,是ok的。但是如果过长,则会造成cpu资源的浪费。
轻量级锁的更新流程:
在这里插入图片描述
而锁对象的markWorld也进行相应的更改

  • 线程在自己的栈里面创建LockRecord
  • 将锁对象的markWorld复制过来
  • 将LockRecord的owner指针指向锁对象
  • 将锁对象的MarkWorld替换为指向LockRecord的指针
    如下图:
    在这里插入图片描述
    随后更改后:
    在这里插入图片描述
    可以通过JVM参数preBlockSpin来控制自旋数量
    当CAS设置锁对象的MarkWorld失败的时候,就会膨胀微重量级锁。

重量级锁

重量级锁就是1.5之前的synchronized锁~通过java -p看class信息可以看出指令即monitorenter和monitorexit来控制锁的加锁和释放。
在这里插入图片描述
所有的Java Object天生携带一个monitor,可以认为是一个同步对象,通过对于对象监视器的争抢修改锁标志从而进行多线程同步。在markOop.hpp源码可以看到:
在这里插入图片描述
monitor的操作依赖于操作系统的MutexLock(互斥锁)来实现的,线程一旦被阻塞,那么就会从用户态切换到内核调度状态。频繁的内核态和用户态的切换回影响锁的性能。锁竞争monitor的逻辑如下图:
在这里插入图片描述

最后贴一张基于wait和notify的锁加入和释放的图:
在这里插入图片描述
抛砖引玉,整理学习笔记。如有问题随时沟通交流~谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值