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下使用opencv拍照
首先在命令中安装opencv: pip install opencv-python 然后打开notebook: jupyter notebook 建立文件,写入如下代码: import cv2 cap ...
- SpringMVC作用域传值几种方式
一.SpringMVC 作用域传值的几种方式 1 使用原生Servlet 1.1 在 HandlerMethod 参数中添加作用域对象 1.1.1 ServletContext不能在方法参数中获取, ...
- SpringMVC环境搭建和详解
1.Spring容器和SpringMVC容器是父子容器 1.1 SpringMVC容器可以调用Spring容器中的所有内容 1.2 图示 2.SpringMVC环境搭建 1.导入jar包 2.在web ...
- springboot深入学习(三)-----docker
一.spring data思路 spring data使用统一的api来对各种数据库存储技术进行数据访问操作提供了支持,包括oracle.mysql.redis.mongoDB等等.主要是通过spri ...
- Win10通知区域图标设置;windows10系统图标合并;Windows10系统通知合并
1.一直喜欢Windows7的通知图标合并 2.通过查阅找到方法 a.输入命令语句 win+R :shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} 回 ...
- .Net实现Windows服务安装完成后自动启动的两种方法
考虑到部署方便,我们一般都会将C#写的Windows服务制作成安装包.在服务安装完成以后,第一次还需要手动启动服务,这样非常不方便. 方法一:在安装完成事件里面调用命令行的方式启动服务 此操作之前要先 ...
- 详细介绍jQuery.outerWidth() 函数具体用法
outerWidth()函数用于设置或返回当前匹配元素的外宽度.外宽度默认包括元素的内边距(padding).边框(border),但不包括外边距(margin)部分的宽度.你也可以指定参数为true ...
- WebGIS实现在线要素编辑之ArcGIS Server 发布Feature Service 过程解析
WebGIS实现在线要素编辑之ArcGIS Server 发布Feature Service 过程解析 FeatureService也称要素服务,其最大的好处就是支持在线要素编辑,并将编辑同步更新到后 ...
- REST WebService与SOAP WebService的比较
在SOA的基础技术实现方式中WebService占据了很重要的地位,通常我们提到WebService第一想法就是SOAP消息在各种传输协议上交互.近几年REST的思想伴随着SOA逐渐被大家接受,同时各 ...
- CMake和静态库顺序
目录 目录 1 前言 1 方法 1 附1:链接静态库的顺序问题 2 附2:再议GCC编译时的静态库依赖次顺问题 3 附3:gcc链接参数--whole-archive的作用 4 附4:让有些“-l”链 ...