AQS理解之三,由刚才写的锁转变成一个公平锁

在第二节里我们实现了一个不公平的锁,之所以说它不公平,主要是因为加锁后解锁时,阻塞的其他线程获取到的锁的可能是随机的,并不是按照顺序来确定的,如果要转变为公平锁,我们应该要记录这个进入的顺序,并在解锁时必须满足是第一个阻塞等待的线程才解锁。

其次,在上一节我们实现的锁是一个自旋阻塞等待的,这样的话线程还是在继续白白工作的,我们在这里也进行优化,使用LockSupport来优化。

我们定义一个链表来保存阻塞的线程,在取出时从链表中取出即可。

这里我们实现了一个简单的公平锁,用Node链表保存了阻塞的线程,在unlock时取出最先的一个进行解锁。

class MyLock{private Thread ownerThread;private volatile AtomicInteger state;private boolean isFair;private volatile Node head;static class Node{private volatile Node pre;private volatile Node next;private volatile Thread thread;public Node(Thread thread){this.thread = thread;}@Overridepublic String toString() {return "Node{" +", thread=" + thread==null?"null":thread.getName() +'}';}}public MyLock(boolean isFair){state = new AtomicInteger(0);head = new Node(null);this.isFair = isFair;}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)) {System.out.println(Thread.currentThread());setOwnerThread(Thread.currentThread());return true;}if (isFair){Node temp = head;while(temp.next !=null){temp = temp.next ;}//将阻塞的线程放入链表的队尾。temp.next = new Node(Thread.currentThread());temp.next.pre = temp;LockSupport.park();}}public void unlock(){if (Thread.currentThread() != getOwnerThread()){throw new RuntimeException("不是锁持有线程,不能解锁");}setOwnerThread(null);state.decrementAndGet();if(isFair){Node temp = head;Node unlockNode = head.next;if (unlockNode!=null&&unlockNode.thread!=null){LockSupport.unpark(unlockNode.thread);temp.next = unlockNode.next;if(unlockNode.next!=null){unlockNode.next.pre = temp;}}Node temp1 = head;while (temp1!=null){System.out.println("unlock"+temp1.thread);temp1 = temp1.next;}}}
}

但是需要注意,我们这里的代码是错误的,因为对head节点的操作位于多个线程,而代码里的操作不是原子性的,所以会有问题,所以我们可以用AtomicReference变量来存储,借助这个类来实现原子操作

AQS理解之三,由刚才写的锁转变成一个公平锁相关推荐

  1. 基础篇:独占锁、共享锁、公平锁、非公平锁,叫我如何分得清

    文章目录 引言 锁的独占与共享 内置锁和显式锁的排他性 AQS 的模板方法 共享锁应用案例 锁的公平与非公平 插队的诱惑 内置锁和显式锁的公平性 启示录 引言 本文继续讲解 Java 并发编程实践的基 ...

  2. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等...

    http://blog.51cto.com/13919357/2339446 Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容 ...

  3. Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等

    Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互 ...

  4. Java多线程系列--“JUC锁”05之 非公平锁

    转载自:http://www.cnblogs.com/skywang12345/p/3496651.html点击打开链接 概要 前面两章分析了"公平锁的获取和释放机制",这一章开始 ...

  5. java 共享锁 独占锁_java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁...

    一.公平锁与非公平锁 1.1 概述 公平锁:是指多个线程按照申请锁的顺序来获取锁. 非公平锁:是指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁,在高并发的情 ...

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

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

  7. 公平锁非公平锁的实际使用_面经手册 · 第16篇《码农会锁,ReentrantLock之公平锁讲解和实现》...

    作者:小傅哥 博客:https://bugstack.cn 专题:面经手册 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 Java学多少才能找到工作? 最近经常有小伙伴问我,以为我的经验来看 ...

  8. Java 独占锁与共享锁、公平锁与非公平锁、可重入锁

    目录 背景 独占锁与共享锁 独占锁 共享锁 公平锁与非公平锁 公平锁 非公平锁 可重入锁 总结 背景 最近有一些小伙伴会问我一些关于并发相关的问题,在与他们的沟通中,我发现他们对锁的概念很模糊.这部分 ...

  9. 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁【Java面试题】

    第二季:5值传递和引用传递[Java面试题] 前言 推荐 值传递 说明 题目 24 TransferValue醒脑小练习 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自 ...

最新文章

  1. 聊一聊Spring中的线程安全性
  2. Windows 2003服务器维护的几个技巧
  3. python2定点找色_Python实现按键精灵(二)-找图找色
  4. Meta分析到底该怎么选题?
  5. 快速开发框架,及库存管理系统,基于easyui框架和C#语言MVC、EntityFrameWork、T4模板技术。...
  6. 【题解】Luogu P2347 砝码称重
  7. nodejs对mongodb数据库的增删改查操作(转载)
  8. 是什么摧毁了程序员的工作效率
  9. 【博客迁移】hyrepo.com
  10. DSOframer 微软官方API的查阅方法
  11. 车票预订系统 搭建服务器,火车票网上订票系统的设计与实现.doc
  12. python chardet_【已解决】windows下,安装python的chardet
  13. 其实创业做生意想成功,本质就两条:流量、变现
  14. nodejs服务器部署unexpected token{
  15. 新视野大学英语第三版 读写(2020.12.05)
  16. 收藏!用Python一键批量将任意结构的CSV文件导入MySQL数据库。
  17. 骨传导耳机怎么选?一文告诉你骨传导耳机推荐哪个牌子
  18. 嵌入式硬件(四)常用模拟集成电路
  19. 协同过滤算法(基于用户)
  20. 数据仓库(六)---分布式SQL查询引擎---presto介绍

热门文章

  1. linux mysql 客户端编码设置_Windows、Linux系统下mysql编码设置方法_MySQL
  2. matlab电力系统潮流计算,大神们,求个电力系统潮流计算的matlab程序。
  3. 知乎回答多线程爬虫案例
  4. 【Python金融量化 8- 100 】八、计算投资组合风险
  5. redis 启动无输出_深入剖析Redis系列: Redis入门简介与主从搭建
  6. 邮件发送代码--网易服务器代理
  7. 从LXMERT到VLMO:多模态预训练模型的演变史
  8. Bengio等人新作:基于双层规划的端到端分子构象生成框架
  9. 如何理解 Graph Convolutional Network (GCN)?
  10. 能量视角下的GAN模型:GAN=“挖坑”+“跳坑”