2020-12-31

那些年我们一起追过的锁【多线程中锁介绍】

 图南

前言:在学习多线程过程中,我们知道为了保证线程安全,我们常常需要使用到线程锁,但是各种锁到底怎么去理解呢?首先,我们需要知道各种名称的锁并不全是对立关系,只是从不同的角度去分析问题,因此网上对于各种锁的介绍也不尽相同,

重要的是从自己的角度去理解其中的原理,这里仅代表个人理解的角度,如有遗漏错误,还请指正!

例如:乐观锁属于轻量级锁,悲观锁中也可能有乐观锁的具体实现。

下面简单介绍一下各种锁:

乐观锁:总是假设最好的情况,每次拿数据都认为别人不会修改,但是在修改时会判断在此期间数据是否被修改。适用于读操作较多的情况,不会产生任何锁和死锁问题。

我们知道乐观锁不会产生锁,只是不断在循环中尝试CAS算法。

CAS(Compare And Swap比较并且替换):是乐观锁的一种实现,属于轻量级锁,
CAS如何实现线程安全的?
线程在读取数据的时候不进行加锁,准备写数据时,先去查询原数据,判断是否被其他线程修改,如果没被修改,则写入;若被修改,则重新执行读取流程。

悲观锁:对数据被修改总是假设最坏的情况,因此在整个数据处理过程中,让数据处于锁定状态,其他线程访问数据都被阻塞挂起。

悲观锁的实现:
1.传统的关系型数据库使用这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
2.Java 里面的同步 synchronized 关键字的实现。
悲观锁主要分为共享锁和排他锁:
共享锁【shared locks】又称为读锁,简称S锁。顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
排他锁【exclusive locks】又称为写锁,简称X锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据行读取和修改。

 

Java1.6之后对于synchronized进行了优化,引入了偏向锁和轻量级锁,目的是为了简化不同情况下的执行过程。先使用偏向锁优先同一线程然后再次获取锁,如果失败就升级为CAS轻量级锁,如果失败就会短暂自旋,防止线程被挂起,如果以上都失败就转换为重量级锁(锁只能升级不能降级)

偏向锁:当一个线程执行到某段代码时,判断是否获取过锁,没有就把标志位修改为1,表示锁已经被获取。之后,同一线程获取该锁只需要把标志位+1,此时就是偏向锁。

轻量级锁(自旋锁): 在偏向锁的基础上,一旦有第二个线程加入锁竞争,偏向锁就升级为轻量级锁(自旋锁)。这里要明确一下什么是锁竞争:如果多个线程轮流获取一个锁,但是每次获取锁的时候都很顺利,没有发生阻塞,那么就不存在锁竞争。只有当某线程尝试获取锁的时候,发现该锁已经被占用,只能等待其释放,这才发生了锁竞争,此时线程属于忙等状态。 长时间自旋非常耗费资源,一般多个线程用一个锁,没有发生锁竞争或者轻微锁竞争,就使用轻量级锁,允许短时间的忙等状态, 这是一种折衷的想法,短时间的忙等,换取线程在用户态和内核态之间切换的开销 。

重量级锁:当锁竞争激烈的时候,默认自旋超过10次,就会将轻量级锁升级为重量级锁(CAS修改锁标志位,不修改持有锁线程的ID),后续线程发现锁属于重量级锁,将自己挂起,不再处于忙等状态,等待被唤醒。

可重入锁(递归锁): 允许同一个线程多次获取同一把锁 。synchronized和ReentrantLock都属于可重入锁。

不可重入锁: 只判断这个锁有没有被锁上,只要被锁上申请锁的线程都会被要求等待。

可中断锁: 可以响应中断的锁 。在Java中,synchronized就不是可中断锁,而Lock是可中断锁。如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁

公平锁:当锁释放的时候,按照先申请先得到的原则,直接从队列中排在第一位的线程获取锁。

判断流程:

1.使用CAS判断,state是否为0,不是则进入队列等待

2.查看队首是否是自己

3.获取锁

 

非公平锁:当所释放的时候,不是先后顺序,可能队列中的线程随机或者按照优先级获取到锁。

1.持有锁的线程A执行完,修改state为0,准备去唤醒队列第一的线程B

2.线程C来到发现state为0,直接CAS修改为1,获取锁

3.线程B发现state为1,只能重新回到队列

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值