ReentrantLock的实现是基于其内部类FairSync(公平锁)和NonFairSync(非公平锁)实现的。 其可重入性是基于Thread.currentThread()实现的: 如果当前线程已经获得了执行序列中的锁, 那执行序列之后的所有方法都可以获得这个锁。

公平锁:

公平和非公平锁的队列都基于锁内部维护的一个双向链表,表结点Node的值就是每一个请求当前锁的线程。公平锁则在于每次都是依次从队首取值。

锁的实现方式是基于如下几点:

表结点Node和状态state的volatile关键字。

sum.misc.Unsafe.compareAndSet的原子操作(见附录)。

非公平锁:

在等待锁的过程中, 如果有任意新的线程妄图获取锁,都是有很大的几率直接获取到锁的。

ReentrantLock锁都不会使得线程中断,除非开发者自己设置了中断位。

ReentrantLock获取锁里面有看似自旋的代码,但是它不是自旋锁。

ReentrantLock公平与非公平锁都是属于排它锁。

公平锁和非公平锁在说的获取上都使用到了 volatile 关键字修饰的state字段, 这是保证多线程环境下锁的获取与否的核心。

但是当并发情况下多个线程都读取到 state == 0时,则必须用到CAS技术,一门CPU的原子锁技术,可通过CPU对共享变量加锁的形式,实现数据变更的原子操作。

volatile 和 CAS的结合是并发抢占的关键。

公平锁的实现机理在于每次有线程来抢占锁的时候,都会检查一遍有没有等待队列,如果有, 当前线程会执行如下步骤:

/**

* Fair version of tryAcquire. Don't grant access unless

* recursive call or no waiters or is first.

*/

protected final boolean tryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (!hasQueuedPredecessors() &&

compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

}

else if (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc < 0)

throw new Error("Maximum lock count exceeded");

setState(nextc);

return true;

}

return false;

}

其中hasQueuedPredecessors是用于检查是否有等待队列的。

非公平锁在实现的时候多次强调随机抢占:

/**

* Performs lock. Try immediate barge, backing up to normal

* acquire on failure.

*/

final void lock() {

if (compareAndSetState(0, 1))

setExclusiveOwnerThread(Thread.currentThread());

else

acquire(1);

}

当当前拥有锁的线程释放锁之后, 且非公平锁无线程抢占,就开始线程唤醒的流程。

通过tryRelease释放锁成功,调用LockSupport.unpark(s.thread); 终止线程阻塞

private void unparkSuccessor(Node node) {

// 强行回写将被唤醒线程的状态

int ws = node.waitStatus;

if (ws < 0)

compareAndSetWaitStatus(node, ws, 0);

Node s = node.next;

// s为h的下一个Node, 一般情况下都是非Null的

if (s == null || s.waitStatus > 0) {

s = null;

// 否则按照FIFO原则寻找最先入队列的并且没有被Cancel的Node

for (Node t = tail; t != null && t != node; t = t.prev)

if (t.waitStatus <= 0)

s = t;

}

// 再唤醒它

if (s != null)

LockSupport.unpark(s.thread);

}

非公平锁性能高于公平锁性能的原因:

在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。

假设线程A持有一个锁,并且线程B请求这个锁。由于锁被A持有,因此B将被挂起。当A释放锁时,B将被唤醒,因此B会再次尝试获取这个锁。与此同时,如果线程C也请求这个锁,那么C很可能会在B被完全唤醒之前获得、使用以及释放这个锁。这样就是一种双赢的局面:B获得锁的时刻并没有推迟,C更早的获得了锁,并且吞吐量也提高了。

当持有锁的时间相对较长或者请求锁的平均时间间隔较长,应该使用公平锁。在这些情况下,插队带来的吞吐量提升(当锁处于可用状态时,线程却还处于被唤醒的过程中)可能不会出现。

mysql的锁是公平的么_lock 默认公平锁还是非公平锁?公平锁是如何定义?如何实现...相关推荐

  1. 【代码】ReentrantLock还可以指定为公平锁

    ReentrantLock还可以指定为公平锁 默认非公平 参数为true表示为公平锁,请对比输出结果 import java.util.concurrent.locks.ReentrantLock;/ ...

  2. mysql触发器行锁_MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁

    需求: 有一个账户,两个人在同一时间要对此账户操作,A要对账户充值100块,B要从账户中取出100块.操作前都要先看一下账户的 余额然后再操作. --窗口1 用户进行充值 --充值前 先查看余额 se ...

  3. 存储过程没有执行完后没有释放锁_【大厂面试07期】说一说你对synchronized锁的理解?...

    PS:本文已收录到1.3 K+ Star 数的开源项目-<大厂面试指北>,如果想要了解更多,可以看一看,项目地址如下: https://github.com/NotFound9/inter ...

  4. java中怎么判断一段代码时线程安全还是非线程安全_24张图带你彻底理解Java中的21种锁...

    (给ImportNew加星标,提高Java技能) 转自:悟空聊架 本篇主要内容如下: 本篇文章已收纳到我的 Java 在线文档. Github.我的 SpringCloud 实战项目持续更新中. 帮你 ...

  5. 还不会使用分布式锁?教你三种分布式锁实现的方式

    摘要:在单进程的系统中,当存在多个线程可以同时改变某个变量时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量,而同步本质上通过锁来实现. 本文分享自华为云社区<还不 ...

  6. 还记得那场关于“分布式锁”的经典论战吗?

    锁的目的在于对于共享资源访问的一个互斥控制,单机场景下我们可以基于jvm的锁进行实现就ok了,分布式场景下的实现方案有很多,有人可能会想到基于redis实现. 有关Redis分布式锁的文章可谓多如牛毛 ...

  7. java 7 锁优化_自Java 6/Java 7开始,Java虚拟机对内部锁的实现进行了一些优化。这些优化主要包括锁消除(Lock Elision)、锁粗化(Lock Coarse...

    自Java 6/Java 7开始,Java虚拟机对内部锁的实现进行了一些优化.这些优化主要包括锁消除(Lock Elision).锁粗化(Lock Coarsening).偏向锁(Biased Loc ...

  8. 华为手机锁屏下拉怎么设置_华为手机怎么设置会滚动的锁屏文字?设置步骤超简单,一看就会...

    小米手机设置锁屏滚动文字是通过自定义运营商名称来实现的,但是华为手机并不能自定义运营商名称,大部分华为手机只能选择显示或不显示运营商名称.那么问题来了,华为手机要怎么操作才能让锁屏文字滚动起来呢?按照 ...

  9. 【已解决】小米手机5解BL锁时出现错误码20091怎么办?| 小米手机5怎么解Bootloader锁 | 小米5获取ROOT权限 | 小米手机5卡槽坏了无法正常读取手机卡怎么解锁BL

    文章目录 1. 按 2. 问题详细描述 3. 操作步骤 3.1. 确保不是隐藏ID(隐藏)的机器 3.2. 使用高通9008模式降级MIUI 3.3. 使用低版本的MIUI绑定账号 3.4. 使用解锁 ...

最新文章

  1. 十一月第三周学习进度条
  2. poj_3067 树状数组
  3. mysql安装文档_mysql安装文档
  4. 【大会】QoE也能驱动业务创新
  5. ddl dml dcl
  6. 如何查看vantUI官方组件的.vue文件(抛转篇)
  7. 技术人生:希望有生之年开发一个“自己的解释语言”
  8. 最新中烟新商盟JS逆向分析实战教程
  9. 使用.net的Cache框架快速实现Cache操作
  10. elasticsearch入门(三)
  11. CMOS电路中闩锁效应产生的原因、过程以及后果
  12. Android仿微信朋友圈10s视频编辑
  13. WebSphere 环境搭建
  14. 清华学霸尹成Python教程
  15. git:remote: [session-f044bfa6] well: Incorrect username or password (access token)
  16. CMD/DOS学习笔记
  17. 人体的神经系统图 分布,神经系统分布图解析图
  18. DB2错误代码大全(含实际开发中遇到的最多的问题)
  19. 最新详细版Ubuntu20.04安装教程
  20. 论文检测平台不同查重结果差异大吗?

热门文章

  1. 吞吐量-Corda的故事
  2. java知识回顾_Java7 –回顾
  3. Fn函数来构建Oracle ADF应用程序
  4. 在一个Java版本上运行Eclipse IDE,但在另一个Java版本上运行
  5. idea使用junit测试_在JUnit测试中使用Builder模式
  6. Wildfly Swarm,朝着成熟和一小部分贡献
  7. Mockito教程:使用Mockito进行测试和模拟
  8. lcs文本相似度_具有LCS方法的通用文本比较工具
  9. 具有Rx-Java的Couchbase Java SDK
  10. 避免不必要的Spring配置组件扫描