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理解之二,自己设计一个锁相关推荐

  1. linux僵尸进程理解,Linux为什么要设计一个“僵尸进程”状态?

    评论 # re: Linux为什么要设计一个"僵尸进程"状态? 2011-05-24 12:34 nevergone 因为linus是僵尸:-(  回复  更多评论 # re: L ...

  2. JAVA实验二:设计一个教师类Teacher(属于cn.net.sdkd包)实现接口进行排序等

    设计一个教师类Teacher(属于cn.net.sdkd包) (1)属性有编号(int no).姓名(String name).年龄(int age).所属学院(String seminary),为这 ...

  3. html制作自动切换音乐按钮代码,HTML5+JavaScript+CSS实现音乐播放器——难点二:自己设计一个控制音乐播放的控制器...

    我们都知道HTML5给我们提供了"controls"这个插件,可是这个插件却比较丑,还不能实现上一首下一首的播放,以及进度条的手动改变等功能,那么如何自己设计一个控制音乐播放的控制 ...

  4. 文件系统(二)—如何设计一个文件系统

    前面一章主要学习了文件系统的存储和分配方式的理论知识,本章接着理论知识,如何设计一个文件系统(本章不涉及任何代码实现),其主要的内容包括如下: 如何一步步设计一个文件系统,了解文件系统由那些组成 当我 ...

  5. 深入理解并发编程之CAS无锁机制与ABA问题

    深入理解并发编程之CAS无锁机制与ABA问题 文章目录 深入理解并发编程之CAS无锁机制与ABA问题 前言 一.什么是CAS无锁机制 二.CAS原理分析 1.AtomicLong自增分析 2.基于At ...

  6. abb伺服电机如何进行挑选_PLC是怎么控制伺服电机的?如何设计一个伺服系统?...

    点上面蓝色字体直观学机械可长期订阅我们 法律顾问:赵建英律师 (一)PLC是怎么控制伺服电机的? 在回答这个问题之前,首先要清楚伺服电机的用途,相对于普通的电机来说,伺服电机主要用于精确定位,因此大家 ...

  7. 从0设计一个基于Redis的锁服务

    作者:温灏,后端研发,专注于Python和Go,对分布式系统感兴趣,本文系作者投稿,有兴趣投稿的同学,请后台回复[投稿] 由于微服务大行其道,服务之间的协调工作变得越来越重要.今天来简单说一下如何搭建 ...

  8. 斯坦福大学马腾宇:无法理解现有的深度学习算法?那就设计一个能理解的

    2020-01-22 05:41:34 作者 | 丛末 编辑 | Camel 本科毕业于清华姚班.博士毕业于普林斯顿大学,师从 Sanjeev Arora 教授,马腾宇作为 AI 学界一颗冉冉升起的新 ...

  9. AQS理解之四—看看我们写的和 ReentrantLock 的公平不公平锁的区别

    AQS理解之四,看看我们写的和 ReentrantLock 的公平不公平锁的区别 首先看下ReentrantLock的lock和unlock方法. 不公平锁版本lock方法 final void lo ...

最新文章

  1. 《IT咨询指南》读书笔记一开卷 前言
  2. 浙江高校计算机等级考试二级办公,浙江省高校计算机等级考试二级(高级办公)试题12.ppt...
  3. ios html5 网页取消默认样式
  4. JAVA 从菜鸟成长为大牛的必经之路
  5. 【Spring】Spring注解配置okhttp3
  6. android studio防止反编译,防反编译利器-Android studio混淆代码压缩apk包体积
  7. 5. soapui 测试
  8. 程序员眼中的统计学(3)】概率计算:把握机会
  9. mysql宾馆客房管理系统视频_java swing mysql实现的酒店宾馆管理系统项目源码附带视频指导运行教程...
  10. 计算机应用基础说课稿的模板,计算机应用基础说课稿模板.doc
  11. 网络安全理论与技术概述-带你了解网络安全
  12. sqldbx连接Smartbi mysql知识库
  13. 大豆技术面分析_大豆高产栽培技术分析,科学施肥很关键,建议收藏
  14. 理想评价鸿蒙系统,鸿蒙系统来了!前期如何发育?后期的潜力有多大?苹果真豁口了!...
  15. Perl之正则表达式基础(一)
  16. 【机器学习】线性判别式(LDA/FLD)
  17. 英语前后缀大全 - 快速理解英语单词
  18. 展锐智能机平台sc9820e调试pwm背光所遇问题小结
  19. uni-app 地图手绘图覆盖方案,类似智慧景区小程序
  20. goodbye 2016 A New Year and Hurry

热门文章

  1. mysql实现日志系统_基于Hadoop/CloudBase/MySQL的日志分析系统的设计与实现
  2. 我的世界java版移除猪灵了吗_我的世界:激怒僵尸猪灵有奖励,用菌光体堆肥,修复126个漏洞!...
  3. android 调用本地第三方应用软件,如qq、微信、微博和视频播放器等
  4. nginx.conf 基本配置模板和结构
  5. docker搭建redis
  6. 聚类(中)层次聚类 基于密度的聚类算法
  7. 研究生一年级,非计算机专业,自学机器学习现实吗?
  8. 「AI在左,营销在右」互动营销创意破圈,这事儿不难
  9. 再谈对比学习:更好的对比样本选择,更好的对比效果
  10. ICCV2017 论文解读:基于图像检索的行人重识别 | PaperDaily #13