Synchronzied(内置锁)
原文地址:深入JVM锁机制1-synchronized
1. 线程的状态与转换
当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态用来区分请求的线程:
- Contention List:所有请求锁的线程将被首先放置到该竞争队列
- Entry List:Contention List 中那些有资格成为候选人(怎么才算有资格成为候选人)的线程被移到 Entry List
- Wait Set:那些调用wait方法被阻塞的线程被放置到Wait Set
- OnDeck:任何时刻最多只能有一个线程正在竞争锁(不是大家一起抢吗?),该线程称为 OnDeck
- Owner:获得锁的线程称为 Owner
- !Owner:释放锁的线程
新请求锁的线程将首先被加入到ConetentionList中,当某个拥有锁的线程(Owner状态)调用unlock之后,如果发现EntryList为空则从ContentionList中移动线程到EntryList
1.1 ContentionList虚拟队列
- ContentionList并不是一个真正的Queue,而只是一个虚拟队列,原因在于ContentionList是由Node及其next指针逻辑构成,并不存在一个Queue的数据结构。
- ContentionList是一个后进先出(LIFO)的队列,每次新加入Node时都会在队头进行,通过CAS改变第一个节点的的指针为新增节点,同时设置新增节点的next指向后续节点,而取得操作则发生在队尾。显然,该结构其实是个Lock-Free的队列。
- 因为只有Owner线程才能从队尾取元素,也即线程出列操作无争用,当然也就避免了CAS的ABA问题。
1.2 EntryList
- EntryLis 与 ContentionList逻辑上同属等待队列,ContentionList 会被线程并发访问,为了降低对 ContentionList 队尾的争用,而建立EntryList。
- Owner线程在unlock时会从ContentionList中迁移线程到EntryList,并会指定EntryList中的某个线程(一般为Head)为Ready(OnDeck)线程。
- Owner线程并不是把锁传递给OnDeck线程,只是把竞争锁的权利交给OnDeck,OnDeck线程需要重新竞争锁。这样做虽然牺牲了一定的公平性,但极大的提高了整体吞吐量,在Hotspot中把OnDeck的选择行为称之为“竞争切换”。
- OnDeck线程获得锁后即变为owner线程,无法获得锁则会依然留在EntryList中,考虑到公平性,在EntryList中的位置不发生变化(依然在队头)。
- 如果Owner线程被wait方法阻塞,则转移到WaitSet队列;如果在某个时刻被notify/notifyAll唤醒,则再次转移到EntryList。
2. 自旋锁
- 如果平均负载小于CPUs则一直自旋
- 如果有超过(CPUs/2)个线程正在自旋,则后来线程直接阻塞
- 如果正在自旋的线程发现Owner发生了变化则延迟自旋时间(自旋计数)或进入阻塞
- 如果CPU处于节电模式则停止自旋
- 自旋时间的最坏情况是CPU的存储延迟(CPU A存储了一个数据,到CPU B得知这个数据直接的时间差)
- 自旋时会适当放弃线程优先级之间的差异
3. 偏向锁
3.1 CAS及SMP架构
3.2 偏向解除
4. 总结
Synchronzied(内置锁)的更多相关文章
- java并发编程(一)可重入内置锁
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁或监视器锁.线程在进入同步代码块之前会自动获取锁,并且在退出同步代码块时会自动释放锁.获得内置锁的唯一途径就是进入由这个锁保护的同步代码块 ...
- synchronized内置锁
synchronized内置锁,如果发生阻塞,无法被中断,除非关闭jvm.因此不能从死锁中恢复.
- java synchronized内置锁的可重入性和分析总结
最近在读<<Java并发编程实践>>,在第二章中线程安全中降到线程锁的重进入(Reentrancy) 当一个线程请求其它的线程已经占有的锁时,请求线程将被阻塞.然而内部锁是可重 ...
- 转:【Java并发编程】之一:可重入内置锁
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁或监视器锁.线程在进入同步代码块之前会自动获取锁,并且在退出同步代码块时会自动释放锁.获得内置锁的唯一途径就是进入由这个锁保护的同步代码块 ...
- 深入理解Java内置锁和显式锁
synchronized and Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两 ...
- 使用ReentrantLock和Condition来代替内置锁和wait(),notify(),notifyAll()
使用ReentrantLock可以替代内置锁,当使用内置锁的时候,我们可以使用wait() nitify()和notifyAll()来控制线程之间的协作,那么,当我们使用ReentrantLock的时 ...
- Java内置锁synchronized的实现原理
简述Java中每个对象都可以用来实现一个同步的锁,这些锁被称为内置锁(Intrinsic Lock)或监视器锁(Monitor Lock). 具体表现形式如下: 1.普通同步方法,锁的是当前实例对象 ...
- 内置锁(一)synchronized 介绍与用法
一.synchronized 的介绍 synchronized 是 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码,而这段代码也被称 ...
- 内置锁(二)synchronized下的等待通知机制
一.等待/通知机制的简介 线程之间的协作: 为了完成某个任务,线程之间需要进行协作,采取的方式:中断.互斥,以及互斥上面的线程的挂起.唤醒:如:生成者--消费者模式.或者某个动作完成,可以唤醒下一 ...
随机推荐
- python早期看书笔记
- 2019.01.16 bzoj3526: [Poi2014]Card(线段树)
传送门 线段树菜题. 题意:有一些卡牌,正反各有一个数,你可以任意翻转,每次操作会将两张卡牌的位置调换,你需要在每次操作后回答以现在的卡牌顺序能否通过反转形成一个单调不降的序列. 思路: 对于一个线段 ...
- 2019.01.14 bzoj2752: [HAOI2012]高速公路(线段树)
传送门 线段树菜题. 题意简述:给一条nnn个点的链,链有边权,支持区间修改边权,查询在一段区间内随机选择不同的起点和终点路径的期望总边权和. 思路:考虑每条边的贡献. 考虑对于一段区间[l,r][l ...
- java中正则表达式常用方法
一.匹配 String matches()方法.用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false. 举例: public static void checkQQ(){ Stri ...
- mysql的myBatis,主键自增设置
方法一: insert id="insert" parameterType="Person" useGeneratedKeys="true" ...
- c# 得到list符合某条件的索引值,排序
请教,在List集合中怎么得到元素的索引值,参考:http://www.myexception.cn/c-sharp/385022.html 这个可以用来读取窗口的多个textbox控件中内容: -- ...
- ThinkPHP3.2.3:使用模块映射隐藏后台真实访问地址
例如:项目应用目录/Application下模块如下,默认后台模块为Admin 现在需要修改后台模块的访问地址,以防被别有用心的人很容易就猜到,然后各种乱搞... (在公共配置文件/Applicati ...
- Language Oriented Programming:下一代编程样式 Part I (翻译)
原文信息 原文地址 作者信息 Sergey Dmitriev JetBrains Sergey Dmitriev is the cofounder and CEO of JetBrains Inc., ...
- js 数组操作函数有:push,pop,join,shift,unshift,slice,splice,concat
(1)push 和 pop 这两个函数都是对数组从尾部进行压入或弹出操作.push(arg1,arg2,...)可以每次压入一个或多个元素,并返回更新后的数组长度.注意如果参数也是数组的话,则是将全部 ...
- webService之helloword(web)
spring 整合webservice pom.xml文件 <dependencies> <!-- CXF WS开发 --> <dependency> <gr ...