学习记录 - Java中Synchronized和ReentrantLock锁

这个月忙着期末考试还有项目对接的事情,忙着忙着就没怎么更新博客了😭
今天请假考试顺便整理下几篇大佬的博客,便于后面复习。

1.Synchronized锁实现原理:

在字节码层面上看,这种加锁方式会在同步块的前后分别加上monitorenter和monitorexit这个两个字节码指令。

(这一段取自文章https://blog.csdn.net/qq_40551367/article/details/89414446。加粗部分为个人补充)
monitorenter
每个对象有一个监视器锁(monitor)(-或者说每个对象会跟一个监视器绑定,加锁释放锁的操作其实是对这个监视器进行操作的)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。

2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1。

3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。

monitorexit
执行monitorexit的线程必须是objectref所对应的monitor的所有者。

指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。

(在这里我从操作系统上的管程去理解,monitorenter至monitorexit这一块交由管程控制,同一时间只能有一个进程可以进入到管程中。)

2.ReentrantLock锁实现原理:

CAS+CLH队列来实现。它支持公平锁和非公平锁,两者的实现类似。

在这里补充一下下,Synchronized锁是非公平锁,ReentrantLock锁通过构建时传入的参数可以设置为公平锁(默认是非公平锁)。公平锁和非公平锁的概念以及性能在文章最后记录下。

CAS:Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。在Java中,CAS主要是由sun.misc.Unsafe这个类通过JNI调用CPU底层指令实现。

CLH队列:带头结点的双向非循环链表

AbstractQueuedSynchronizer
ReentrantLock实现的前提就是AbstractQueuedSynchronizer,简称AQS,是java.util.concurrent的核心,CountDownLatch、FutureTask、Semaphore、ReentrantLock等都有一个内部类是这个抽象类的子类。

由于ReentrantLock我们用的比较多的是非公平锁,所以看下非公平锁是如何实现的。假设线程1调用了ReentrantLock的lock()方法,那么线程1将会独占锁,整个调用链十分简单:

第一个获取锁的线程就做了两件事情:

1、设置AbstractQueuedSynchronizer的state为1

2、设置AbstractOwnableSynchronizer的thread为当前线程

3.公平锁和非公平锁:

参考以下文章:
https://www.jianshu.com/p/f584799f1c77

个人理解两者区分在于获取锁的进程有没有可能被插队,有可能被插队那就是那就不公平啦。下面是大佬的神图解:
在这里插入图片描述

1、若在释放锁的时候总是没有新的兔子来打扰,则非公平锁等于公平锁;
2、若释放锁的时候,正好一个兔子来喝水,而此时位于队列头的兔子还没有被唤醒(因为线程上下文切换是需要不少开销的),此时后来的兔子则优先获得锁,成功打破公平,成为非公平锁;

而非公平锁效率高于公平锁的原因,就在于上文说到的线程切换的开销。因为非公平锁减少了线程挂起的几率,后来的线程有一定几率逃离被挂起的开销。

再次贴出参考文章:

https://www.jianshu.com/p/f584799f1c77

https://blog.csdn.net/javazejian/article/details/72828483

https://blog.csdn.net/qq_40551367/article/details/89414446

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值