博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
重入锁源码之手写 reentrantLock
阅读量:3949 次
发布时间:2019-05-24

本文共 1516 字,大约阅读时间需要 5 分钟。

最近想复习下多线程相关知识,尝试手动造了一个reentrantLock的轮子,

计划根据原理先实现最初级的版本,然后不断重构,最终达到类似原版的效果。

源码地址:

第一版本:实现基本功能,双向链表实现加锁解锁阻塞

reentrantLock的原理是:
1、维护一个双向链表保存被阻塞的线程,链表的每一个节点保存的是线程封装的Node节点对象,
2、如果线程取不到锁,就把线程加入到链表尾部
3、已获取到锁的线程去解锁时,就从链表头部取出一个阻塞线程唤醒
实现代码:
(参考com.bones.locks.myReenterLock.MyReentrantLock)

这样就初步实现了reentrantLock的功能。

存在的问题
线程1加锁, 线程2阻塞时能正常工作
线程1加锁,线程2,线程3阻塞时不能正常工作
这是一个典型的并发问题,因为线程2,3是并行的,对共享变量的操作不能保存原子性

第二版本: 修复bug,操作共享变量时加synchronized关键字保证原子性

实现代码:
(参考com.bones.locks.myReenterLock.MyReentrantLockV2)
经过多次测试,每次都能执行成功,
有时候是线程2先获得锁,有时候是线程3先获得锁

第三版本:性能优化,用volatile+atomic替换synchroneized

实现代码:
(参考com.bones.locks.myReenterLock.MyReentrantLockV3)
测试后发现性能提高的效果不明显
为了验证性能提高,专门写了一个测试类
参考 com.bones.locks.myReenterLock.TestAtomic
实际测试,发现把synchronized 换成atomicInteger速度有提高,但是不明显,1000个线程,累加1000次的情况下,执行时间从280毫秒优化到140毫秒。

4.0版本 实现公平锁,设计模式优化,抽取Sync

第一层抽象,notfairSync和fairSync
公平锁和非公平锁的区别就在于是获取锁时否判断队列中是否有等待线程。
非公平锁不判断等待队列,直接获取锁,有机会先执行。
公平锁需要判断等待队列,等待他的前置节点唤醒他。
如果非公平锁没获取到锁进入队列了,行为就跟公平锁一样了。
因为需要实现公平锁和非公平锁2个版本,
把reentrantLock类改造为notfairSync和fairSync两个类分别实现公平锁和非公平锁
面向接口编程,定义抽象锁Sync,公平锁fairSync和非公平锁notfairSync都是Sync的实现类
reentrantLock做代理类引用Sync
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
reentrantLock.Lock里调用Sync.Lock
reentrantLock.unLock里调用Sync.unLock

5.0版本,实现读写锁信号量,设计模式优化,抽取AQS

第二层抽象,AQS
如果只实现重入锁,Sync已经很完美了,
但是还要实现读写锁和信号量,
他们的不同点主要在于state
重入锁的state只有1和0,
读写锁的state分高低位,
信号量的state从0改变到1要经过多次lock,
他们的相同点是都有公平锁和非公平锁的概念,都可以抽象到Sync这个层级,而他们的Sync有共同点,阻塞队列的数据结构一致
所以Sync还可以继续抽象一层AQS,包含共用的阻塞队列,

转载地址:http://rvhwi.baihongyu.com/

你可能感兴趣的文章
GPS打开失败
查看>>
如何增加电量显示格数,并提示剩余电量?
查看>>
Key Launcher上底下的shortcut如何修改默认值以及如果修改Key Launcher上widget的默认显示顺序
查看>>
Java支持播放哪些multi media格式
查看>>
Audio播放完毕后设置时间无法正确获取
查看>>
打开了一个size不为零的文件,读取到的值却为零的一种分析和解决方法
查看>>
Aplix VM安装Java应用在main menu上不能显示自己的图标,而是显示一朵小花的解决方法
查看>>
Aplix VM安装第一个Java应用在main menu上看不到图标的解决方法
查看>>
java 在cosmos下修改设置,提示“setting are not modifiable”的解释
查看>>
JAD中常见字段的介绍。
查看>>
对于SIM menu update by OTA的解释
查看>>
如何去掉OTA provisioning的PIN码验证
查看>>
如何实现首次开机自动power on 蓝牙?
查看>>
Makefile文件中蓝牙相关的宏介绍
查看>>
如何屏蔽掉乱码的push消息
查看>>
登录一些安全网站,比如twitter/facebook,提示安全链接失败,或提示下载文件。
查看>>
如何去除launcher 上默认的 google search bar.
查看>>
Android如何绘制View
查看>>
23种设计模式的索引
查看>>
Can't make emergency call without SIM card
查看>>