《Java并发编程的艺术》Java并发机制的底层实现原理(二)
Java并发机制的底层实现原理
1.volatile
volatile相当于轻量级的synchronized,在并发编程中保证数据的可见性,使用 valotile 修饰的变量,其内存模型会增加一个 Lock 前缀,而这个前缀在多核处理器中带来的效果是:
(1)会将处理器缓存行的数据回写到内存中;
(2)同时这个操作会使其它处理器里缓存了这个内存地址的数据无效;
2.synchronized
synchronized是重量级锁,其在JVM实现的原理是基于进入和退出 Monitor 对象来实现同步代码块和方法快。在同步代码块中, moitorenter 指令会插入代码块开始的位置,而 monitorexit 指令会插入在代码块结束位置和异常位置,同时这两个指令必须形成闭环。
对象头
在对象头里面,有一个 Mark Word 内容,用于存储对象的 HashCode 和锁信息。
锁的升级与对比
JDK1.6为了减少获得和释放锁带来的性能消耗,引入了 偏向锁 和 轻量级锁 。锁有四个状态(从低到高): 无锁状态 、 偏向锁状态 、 轻量级锁状态 、 重量级锁状态 。锁的状态只能升级不能降级。
偏向锁
偏向锁是基于大多数情况下,不存在线程对锁的竞争,而且锁总是由同一个线程获得,于是有了偏向锁,用于减少一个线程获得锁的开销。
(1)偏向锁的撤销:
偏向锁会一直等到有线程竞争锁的时候才会撤销,在此之前,都通过对象头 Mark Word 里锁信息指向的线程ID来进行获得锁的操作。
(2)偏向锁的关闭:
偏向锁是默认开启的,如果程序中存在较多的线程对锁的竞争,那么可以在JVM配置 -XX:-UseBiasedLocking=false 来关闭偏向锁,否则偏向锁的撤销过程会有性能的消耗。
轻量级锁
(1)轻量级锁加锁:
线程获得锁的时候,会在线程的栈帧分配空间,然后将锁对象的 Mark Word 信息复制过来,然后线程使用CAS将对象头的 Mark Word替换为指向锁的指针。如果失败,表明其它锁竞争锁,则当前线程尝试自旋获得锁;
(2)轻量级锁解锁:
解锁的时候会将栈帧里的 Mark Word 信息使用CAS复制回对象头中,如果成功,则没有线程的竞争,如果失败,则有线程竞争会导致锁膨胀成重量级锁。
3.原子操作的实现原理
原子:不可被进一步分割的原子;原子操作:不可被中断的一个或一系列的操作;
处理器实现原子操作
(1)总线锁保证原子性:
当一个处理器操作一个数据时,总线锁锁住之后,其它处理器就不能操作这个数据了,其它处理器的操作会被阻塞住。
(2)缓存锁保证原子性:
正是因为总线锁会阻塞内存和CPU之间的通信,开销较大,所以有了缓存锁。一个处理器操作一个缓存行里的数据时,缓存锁会锁定这个数据的内存地址,只能由这个处理器进行操作,其它处理器的操作则会无效。
Java实现原子操作
(1)使用CAS算法, compareAndSwap ,比较并替换;
Java提供了并发包里的 AtomicInteger 、 AtomicBoolean 、 AtomicLong 等等类来实现对应基本变量的原子操作;
(2)CAS实现原子操作的三大问题:
①ABA问题:如果仅仅通过判断value是否一致来进行修改,那么可能出现两次修改之后回到原始值的情况,于是添加了版本号就行双重判断;
②循环时间开销大:CAS自旋会一直循环,此操作会给CPU带来一定的开销,如果JVM可以支持处理器提供的 pause 指令的话,那就可以进行一定的程度上效率的提升;
③只能保证一个共享变量的原子操作:如果需要对多个共享变量进行原子操作,那么可以使用Java并发包提供的 AtomicRefrence 类来实现多个共享变量的原子操作;
(3)使用上锁的机制来实现原子操作,而除了偏向锁之外,其它锁都是通过CAS自旋的方式来获得锁;
《Java并发编程的艺术》Java并发机制的底层实现原理(二)的更多相关文章
- JAVA并发编程的艺术 Java并发容器和框架
ConcurrentHashMap ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成. 一个ConcurrentHashMap里包含一个Segment数组, ...
- Java并发编程的艺术(一)——并发编程需要注意的问题
并发是为了提升程序的执行速度,但并不是多线程一定比单线程高效,而且并发编程容易出错.若要实现正确且高效的并发,就要在开发过程中时刻注意以下三个问题: 上下文切换 死锁 资源限制 接下来会逐一分析这三个 ...
- 《Java并发编程的艺术》并发编程的挑战(一)
并发编程的挑战 并发编程的初衷是让程序运行的更快,但是更多的使用多线程真的会让程序变快吗? 1.线程上下文切换 关于线程上下文切换 多个线程在一个处理器里并不是同时进行的,而是非常快速地在线程之间进行 ...
- java并发编程系列七:volatile和sinchronized底层实现原理
一.线程安全 1. 怎样让多线程下的类安全起来 无状态.加锁.让类不可变.栈封闭.安全的发布对象 2. 死锁 2.1 死锁概念及解决死锁的原则 一定发生在多个线程争夺多个资源里的情况下,发生的原因是 ...
- 《Java并发编程的艺术》并发编程的基础(四)
一.线程简介 1.线程的概念 系统运行的最小单元 2.为何使用多线程 更好地利用系统资源(处理器多核心),提高响应速度. 3.线程的状态 NEW(创建状态) RUNABLE(运行状态,系统调度,争抢时 ...
- 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理
二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...
- 那些年读过的书《Java并发编程的艺术》一、并发编程的挑战和并发机制的底层实现原理
一.并发编程的挑战 1.上下文切换 (1)上下文切换的问题 在处理器上提供了强大的并行性就使得程序的并发成为了可能.处理器通过给不同的线程分配不同的时间片以实现线程执行的自动调度和切换,实现了程序并行 ...
- 【java并发编程艺术学习】(三)第二章 java并发机制的底层实现原理 学习记录(一) volatile
章节介绍 这一章节主要学习java并发机制的底层实现原理.主要学习volatile.synchronized和原子操作的实现原理.Java中的大部分容器和框架都依赖于此. Java代码 ==经过编译= ...
- Java并发编程的艺术读书笔记(2)-并发编程模型
title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...
随机推荐
- python之工厂函数
python之工厂函数 本人也是小白一个,最近在学习python工厂函数时随便在网上搜了搜,发现许多人对工厂函数的理解存在误区,同时也是为了整理和记录自己的思路,写下本片博文. 工厂函数顾名思义就是一 ...
- K2项目开发流程
(自己的学习资料) K2项目开发流程: 1.在VS2013中设计流程,并在K2 Workspce中测试流程 首先是新建新建一个k2的Process文件..kprx后缀. 在里面创建所需要的流程.由于我 ...
- JAVA SpringBoot2 关于 JSON 数据处理,基于 ObjectMapper
1,当今的互联网开发行业,JSON 这种数据格式越来越成为网络开发的主流,尤其是前后端分离之后,几乎百分百的数据交互方式都是采用 JSON 2,由于 SpringMVC 框架的封装性,我们日常开发中只 ...
- js常用身份校验规则
js常用身份校验规则 var Validator = { extractBirth: function(id) { // 身份证提取出生年月 var re = null, split, year, m ...
- logstash定时将mysql种数据同步到elasticsearch
以Windows操作系统为例 1.下载logstash安装包,解压,配置好环境 2.在config目录中新增一个jdbc.conf input { stdin { } jdbc { # mysql 数 ...
- linux 查看文件方法
vi 文件名 #编辑方式查看,可修改cat 文件名 #显示全部文件内容more 文件名 #分页显示文件内容tail 文件名 #仅查看尾部,还可以指定行数head 文件名 #仅查看头部,还可以指定行数s ...
- C语言典型编程1
关于C的一些小而精的编程,适合希望提升编程能力的初学者学习:关键编程也就几句,但思维可以迁移到其他编程语言.同一问题,算法多种 //阶乘运算(有多种编写方式,编程需要看懂,更要打出来)#include ...
- mysql in 子查询 效率慢,对比
desc SELECT id,detail,groupId from hs_knowledge_point where groupId in ( UNION all ) UNION ALL SELEC ...
- java后端学习记录2019
学习计划 2019年计划 1.学习计算机基础,并加以实践.包括LeetCode刷题.数据库原理(索引和锁.Sql优化等).网络协议(Http.Tcp).操作系统(加深Linux).<Http权威 ...
- 源码安装支持ffmpeg的opencv2
1.首先安装ffmpeg apt-get install ffmpeg 2.安装opencv对ffmeg的依赖 # for Compiling OpenCV with ffmpeg support ...