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并发机制的底层实现原理(二)的更多相关文章

  1. JAVA并发编程的艺术 Java并发容器和框架

    ConcurrentHashMap ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成. 一个ConcurrentHashMap里包含一个Segment数组, ...

  2. Java并发编程的艺术(一)——并发编程需要注意的问题

    并发是为了提升程序的执行速度,但并不是多线程一定比单线程高效,而且并发编程容易出错.若要实现正确且高效的并发,就要在开发过程中时刻注意以下三个问题: 上下文切换 死锁 资源限制 接下来会逐一分析这三个 ...

  3. 《Java并发编程的艺术》并发编程的挑战(一)

    并发编程的挑战 并发编程的初衷是让程序运行的更快,但是更多的使用多线程真的会让程序变快吗? 1.线程上下文切换 关于线程上下文切换 多个线程在一个处理器里并不是同时进行的,而是非常快速地在线程之间进行 ...

  4. java并发编程系列七:volatile和sinchronized底层实现原理

    一.线程安全 1.  怎样让多线程下的类安全起来 无状态.加锁.让类不可变.栈封闭.安全的发布对象 2. 死锁 2.1 死锁概念及解决死锁的原则 一定发生在多个线程争夺多个资源里的情况下,发生的原因是 ...

  5. 《Java并发编程的艺术》并发编程的基础(四)

    一.线程简介 1.线程的概念 系统运行的最小单元 2.为何使用多线程 更好地利用系统资源(处理器多核心),提高响应速度. 3.线程的状态 NEW(创建状态) RUNABLE(运行状态,系统调度,争抢时 ...

  6. 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理

    二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...

  7. 那些年读过的书《Java并发编程的艺术》一、并发编程的挑战和并发机制的底层实现原理

    一.并发编程的挑战 1.上下文切换 (1)上下文切换的问题 在处理器上提供了强大的并行性就使得程序的并发成为了可能.处理器通过给不同的线程分配不同的时间片以实现线程执行的自动调度和切换,实现了程序并行 ...

  8. 【java并发编程艺术学习】(三)第二章 java并发机制的底层实现原理 学习记录(一) volatile

    章节介绍 这一章节主要学习java并发机制的底层实现原理.主要学习volatile.synchronized和原子操作的实现原理.Java中的大部分容器和框架都依赖于此. Java代码 ==经过编译= ...

  9. Java并发编程的艺术读书笔记(2)-并发编程模型

    title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...

随机推荐

  1. linux光标操作

    看一个真正的专家操作命令行绝对是一种很好的体验-光标在单词之间来回穿梭,命令行不同的滚动. 在这里强烈建立适应GUI节目的开发者尝试一下在提示符下面工作. 但是事情也不是那么简单,还是需要知道“如何去 ...

  2. Swoft 容器使用

    可以借助Swoft下的Bean类操作容器 示例: 将类绑定至容器 use Swoft\Bean\Annotation\Bean; /** * @Bean("imageLogic") ...

  3. nltk-贝叶斯分类器

    本人小白一枚,专业统计,之前做过质量工程,现转行将近一年,开始记录我的学习过程及踩过的坑. 第一篇:用贝叶斯分类器(本文使用NLTK中的NaiveBayesClassifier)将5000多个样本进行 ...

  4. Rocket MQ 2 - Namesrv

    通过上文中使用可以看到,主要逻辑还是在NamesrvController中包含KVConfigManager负责配置相关的读写,RouteInfoManager负责路由信息的管理; 启动定时任务定时打 ...

  5. MySQL8.0.x免安装配置

    目录 概述 下载 配置环境变量 编辑配置文件 初始化MySQL 安装MySQL系统(Windows)服务 初始化MySQL 启动MySQL 修改默认密码 开启远程登录 概述 MySQL从5.7一下子跳 ...

  6. MongoDB基础入门

    1,安装 下载解压安装包 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.5.tgz tar -xvzf mongodb- ...

  7. Spring再接触 Annotation part2

    resource resource beans.xml <?xml version="1.0" encoding="UTF-8"?> <bea ...

  8. PTA变成总结1

    1)实验代码 #include<stdio.h>int main(){ int N,k,n,i,j,p,m,ge; char op; while(1){  scanf("%d % ...

  9. jmeter学习笔记--线程组

    jmeter组件:线程组 是什么? 进程:一个正在执行的程序对应一个进程 线程:进程中的执行线索(一个进程中有多个执行线索) 线程组:按照线程性质对线程进行分组 并发执行:多个线程同时进行    特点 ...

  10. CS通用项目系统搭建——三层架构第二天 (补一篇完整的SqlHelper)

    #region ExecuteNonQuery(如果是增,删,修) /// <summary> /// 执行sql命令 /// </summary> /// <param ...