AQS理解之二,自己设计一个锁
AQS理解之二,自己设计一个锁
一,实现锁的条件
首先我们想一想,如果我们自己实现一个类似于java中的锁,我们可能需要哪些必要的东西:
1,记录是哪个线程持有了锁。
2,如果有一个变量代表加锁,A线程加锁,需要让B线程能看见,这里需要可见性,所以我们可能要用到volatile变量。
3,对变量的操作应该是一个原子操作。
二,实现
首先我们定义一个类,这个类需要有一个持有锁的变量。这里使用ownerThread这个变量来代表持有锁的线程。
class MyLock{private Thread ownerThread;public Thread getOwnerThread() {return ownerThread;}public void setOwnerThread(Thread ownerThread) {this.ownerThread = ownerThread;}
}
我们先简单定义一下加锁和解锁的方法。并设置一个volatile的变量来保证锁的可见性。
class MyLock{private Thread ownerThread;private volatile int state;public Thread getOwnerThread() {return ownerThread;}public void setOwnerThread(Thread ownerThread) {this.ownerThread = ownerThread;}public boolean lock(){//可重入,如果锁设置不可重入,则state应该只能为1和0,并在此处抛出异常。if (Thread.currentThread() == getOwnerThread()){//临时写法,应该为原子操作的++;state++;return true;} else if(state == 0){state++; //这里的判断相等和++操作不应该分开,临时写法。正确方法应该为CAS操作。setOwnerThread(Thread.currentThread());return true;}return false;}public void unlock(){if (Thread.currentThread() != getOwnerThread()){throw new RuntimeException("不是锁持有线程,不能解锁");}state--;setOwnerThread(null);}
}
这里我们看到lock里我们考虑到了可重入性,所以简单实现了一下,如果还要实现lock阻塞,应该加上自旋操作,如:
public boolean lock(){//加上自旋,如果失败,继续。for (;;) {if (Thread.currentThread() == getOwnerThread()){state++;return true;}else if(state == 0){state++;setOwnerThread(Thread.currentThread());return true;}}
}
我们继续完善代码,将之前的临时操作进一步优化。因为我们无法使用unsafe类来操作,我门这里将state修改为AtomicInteger。
class MyLock{private Thread ownerThread;private volatile AtomicInteger state;public MyLock(){state = new AtomicInteger(0);}public Thread getOwnerThread() {return ownerThread;}public void setOwnerThread(Thread ownerThread) {this.ownerThread = ownerThread;}public boolean lock(){//可重入for (;;) {if (Thread.currentThread() == getOwnerThread()){state.incrementAndGet();return true;}else if(state.compareAndSet(0,1)){setOwnerThread(Thread.currentThread());}}}public void unlock(){if (Thread.currentThread() != getOwnerThread()){throw new RuntimeException("不是锁持有线程,不能解锁");}setOwnerThread(null);state.decrementAndGet();}
}
三,验证
public static void testSout(){try{lock.lock();System.out.println("a");Thread.sleep(100);System.out.println("b");Thread.sleep(100);System.out.println("c");Thread.sleep(100);System.out.println("d");Thread.sleep(100);}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}
}public static void main(String[] args) throws InterruptedException {Runnable runnable = new Runnable() {@Overridepublic void run() {TestUtil.testSout();}};Thread thread = new Thread(runnable);Thread thread1 = new Thread(runnable);Thread thread2 = new Thread(runnable);Thread thread3 = new Thread(runnable);thread.start();thread1.start();thread2.start();thread3.start();thread.join();thread1.join();thread2.join();thread3.join();}
控制台可以正常输出,说明我们加的锁是可以用的。
四,总结
在这里我们实现的是一个可重入的,不公平,利用自旋来阻塞的一个锁,后续继续深入。
AQS理解之二,自己设计一个锁相关推荐
- linux僵尸进程理解,Linux为什么要设计一个“僵尸进程”状态?
评论 # re: Linux为什么要设计一个"僵尸进程"状态? 2011-05-24 12:34 nevergone 因为linus是僵尸:-( 回复 更多评论 # re: L ...
- JAVA实验二:设计一个教师类Teacher(属于cn.net.sdkd包)实现接口进行排序等
设计一个教师类Teacher(属于cn.net.sdkd包) (1)属性有编号(int no).姓名(String name).年龄(int age).所属学院(String seminary),为这 ...
- html制作自动切换音乐按钮代码,HTML5+JavaScript+CSS实现音乐播放器——难点二:自己设计一个控制音乐播放的控制器...
我们都知道HTML5给我们提供了"controls"这个插件,可是这个插件却比较丑,还不能实现上一首下一首的播放,以及进度条的手动改变等功能,那么如何自己设计一个控制音乐播放的控制 ...
- 文件系统(二)—如何设计一个文件系统
前面一章主要学习了文件系统的存储和分配方式的理论知识,本章接着理论知识,如何设计一个文件系统(本章不涉及任何代码实现),其主要的内容包括如下: 如何一步步设计一个文件系统,了解文件系统由那些组成 当我 ...
- 深入理解并发编程之CAS无锁机制与ABA问题
深入理解并发编程之CAS无锁机制与ABA问题 文章目录 深入理解并发编程之CAS无锁机制与ABA问题 前言 一.什么是CAS无锁机制 二.CAS原理分析 1.AtomicLong自增分析 2.基于At ...
- abb伺服电机如何进行挑选_PLC是怎么控制伺服电机的?如何设计一个伺服系统?...
点上面蓝色字体直观学机械可长期订阅我们 法律顾问:赵建英律师 (一)PLC是怎么控制伺服电机的? 在回答这个问题之前,首先要清楚伺服电机的用途,相对于普通的电机来说,伺服电机主要用于精确定位,因此大家 ...
- 从0设计一个基于Redis的锁服务
作者:温灏,后端研发,专注于Python和Go,对分布式系统感兴趣,本文系作者投稿,有兴趣投稿的同学,请后台回复[投稿] 由于微服务大行其道,服务之间的协调工作变得越来越重要.今天来简单说一下如何搭建 ...
- 斯坦福大学马腾宇:无法理解现有的深度学习算法?那就设计一个能理解的
2020-01-22 05:41:34 作者 | 丛末 编辑 | Camel 本科毕业于清华姚班.博士毕业于普林斯顿大学,师从 Sanjeev Arora 教授,马腾宇作为 AI 学界一颗冉冉升起的新 ...
- AQS理解之四—看看我们写的和 ReentrantLock 的公平不公平锁的区别
AQS理解之四,看看我们写的和 ReentrantLock 的公平不公平锁的区别 首先看下ReentrantLock的lock和unlock方法. 不公平锁版本lock方法 final void lo ...
最新文章
- 《IT咨询指南》读书笔记一开卷 前言
- 浙江高校计算机等级考试二级办公,浙江省高校计算机等级考试二级(高级办公)试题12.ppt...
- ios html5 网页取消默认样式
- JAVA 从菜鸟成长为大牛的必经之路
- 【Spring】Spring注解配置okhttp3
- android studio防止反编译,防反编译利器-Android studio混淆代码压缩apk包体积
- 5. soapui 测试
- 程序员眼中的统计学(3)】概率计算:把握机会
- mysql宾馆客房管理系统视频_java swing mysql实现的酒店宾馆管理系统项目源码附带视频指导运行教程...
- 计算机应用基础说课稿的模板,计算机应用基础说课稿模板.doc
- 网络安全理论与技术概述-带你了解网络安全
- sqldbx连接Smartbi mysql知识库
- 大豆技术面分析_大豆高产栽培技术分析,科学施肥很关键,建议收藏
- 理想评价鸿蒙系统,鸿蒙系统来了!前期如何发育?后期的潜力有多大?苹果真豁口了!...
- Perl之正则表达式基础(一)
- 【机器学习】线性判别式(LDA/FLD)
- 英语前后缀大全 - 快速理解英语单词
- 展锐智能机平台sc9820e调试pwm背光所遇问题小结
- uni-app 地图手绘图覆盖方案,类似智慧景区小程序
- goodbye 2016 A New Year and Hurry
热门文章
- mysql实现日志系统_基于Hadoop/CloudBase/MySQL的日志分析系统的设计与实现
- 我的世界java版移除猪灵了吗_我的世界:激怒僵尸猪灵有奖励,用菌光体堆肥,修复126个漏洞!...
- android 调用本地第三方应用软件,如qq、微信、微博和视频播放器等
- nginx.conf 基本配置模板和结构
- docker搭建redis
- 聚类(中)层次聚类 基于密度的聚类算法
- 研究生一年级,非计算机专业,自学机器学习现实吗?
- 「AI在左,营销在右」互动营销创意破圈,这事儿不难
- 再谈对比学习:更好的对比样本选择,更好的对比效果
- ICCV2017 论文解读:基于图像检索的行人重识别 | PaperDaily #13