synchronized 和 volatile,是最基础的两个锁!

  volatile是轻量级锁,它在多核处理器开发中保证了共享变量的可见性。即当一个线程修改一个共享变量时,其他线程能够读到这个修改的值。它比syncronized使用和成本更低。

  要说volatile的实现原理,就要先看一下cpu基本概念。java语言规范第3版中对volatile的定义如下:

    volatile会添加一条lock# 前缀的指令在汇编前,使数据立即从缓冲区刷到主内存,同时通过缓存一致性协议,将其他缓存了该内存地址的缓存失效。从而达到内存可见的目的。

  synchronized是重量级锁,它是存放在java对象头里,如图:

  在运行期间,mark word里的数据会随锁标志位变化而变化。

  syncronized 实现锁方法实现为,在进入前加入monitorenter和在退出时monitorexit,每个对象都有一个monitor!

  锁分偏向锁,轻量级锁和重量级锁,偏向锁的前提是线程切换的可能性比较少,在对象头中保存线程偏向标识,在释放锁只需判定该偏向锁是否为需要的即可,如果有竞争则进行锁升级,到轻量级锁,再到重量级锁。锁只能正向升级,不能反向降级;

  cpu中实现原子操作原理为,首先处理器能自动保证基本的内存操作的原子性,从系统内存读取或写入一个字节是原子的,即当一个处理器在读取一个字节时,其他处理器是不能访问这个字节的内存地址的。另外比如某处理器能自动保证单处理器对同一个缓存行里进行16/32/64位的操作是原子的,另外的复杂操作如跨总线宽度跨多缓存行跨页表的访问则是不能保证原子的。但是,处理器提供总线锁定和缓存锁定两个机制来保证复杂内存操作的原子性,从而使锁一类的操作得到了保障。

  其中,总线锁定开销比较大。实现为使用处理器提供的一个lock # 信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,从而使该处理器以独占方式使用内存。

  缓存锁定机制则是为了减轻总线锁带来的巨大开销而出来的,即如果某个操作被处理器缓存在处理器的缓存行里,并且声明了lock #操作,就可以只修改内部的内存地址,并允许它的缓存一致性来保证原子性,缓存一致性会阻止同时修改两个以上处理器缓存的内存区域数据,当其他处理器回写锁定的缓存行时,会使缓存行失效,从而保证操作的原子性。但是两种情况不能用缓存锁定,一操作的数据不能被缓存在处理器内部时,或者操作数据跨多个缓存行时,使用总线锁定;二处理器不支持缓存锁定;

  jmm内存模型为,主内存和工作存,每个线程直接与工作内存交互,在不确定的时间点将数据刷入主内存,只有刷入主内存的数据对其他线程才是可见的。

  锁机制保证了只有获得锁的线程才能操作锁定的内存区域,有偏向锁,轻量级锁和互斥锁,但除了偏向锁外,其他两个都是用cas来实现,即获取锁时用cas保证获取,退出同步块时使用循环cas释放锁。由此可见,cas在java锁实现中的重要地位。

  但是我们也要明白 cas 也有自己的弊端,如ABA问题,循环时间长时开销很大;

  基于cas,java中实现多个常用的原子操作,一般以 AtomicXXX 命名,在需要强一致性多线程操作场景,可以派上用场。

java并发机制锁的类型和实现的更多相关文章

  1. Java 并发机制底层实现 —— volatile 原理、synchronize 锁优化机制

    本书部分摘自<Java 并发编程的艺术> 概述 相信大家都很熟悉如何使用 Java 编写处理并发的代码,也知道 Java 代码在编译后变成 Class 字节码,字节码被类加载器加载到 JV ...

  2. Java 并发系列之二:java 并发机制的底层实现原理

    1. 处理器实现原子操作 2. volatile /** 补充: 主要作用:内存可见性,是变量在多个线程中可见,修饰变量,解决一写多读的问题. 轻量级的synchronized,不会造成阻塞.性能比s ...

  3. Java并发机制的底层实现原理之volatile应用,初学者误看!

    volatile的介绍: Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现 ...

  4. Java并发 - (无锁)篇6

    , 摘录自葛一鸣与郭超的 [Java高并发程序设计]. 本文主要介绍了死锁的概念与一些相关的基础类, 摘录自葛一鸣与郭超的 [Java高并发程序设计]. 无锁是一种乐观的策略, 它假设对资源的访问是没 ...

  5. java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock

    原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...

  6. 《Java并发编程的艺术》Java并发机制的底层实现原理(二)

    Java并发机制的底层实现原理 1.volatile volatile相当于轻量级的synchronized,在并发编程中保证数据的可见性,使用 valotile 修饰的变量,其内存模型会增加一个 L ...

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

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

  8. 从源码学习Java并发的锁是怎么维护内部线程队列的

    从源码学习Java并发的锁是怎么维护内部线程队列的 在上一篇文章中,凯哥对同步组件基础框架- AbstractQueuedSynchronizer(AQS)做了大概的介绍.我们知道AQS能够通过内置的 ...

  9. Java并发编程锁系列之ReentrantLock对象总结

    Java并发编程锁系列之ReentrantLock对象总结 在Java并发编程中,根据不同维度来区分锁的话,锁可以分为十五种.ReentranckLock就是其中的多个分类. 本文主要内容:重入锁理解 ...

随机推荐

  1. 探索未知种族之osg类生物---渲染遍历之Renderer::draw()简介

    我们今天进入上一节的遗留问题Renderer::draw()的探究. 1.从_drawQueue中取出其中一个sceneView对象.SceneView是对scene和view类的封装,通过他可以方便 ...

  2. linux(centos) tomcat设置开机启动

    亲测有效 环境: centos7 apache-tomcat-8.5.37 设置步骤: 1.修改/etc/rc.d/rc.local vi /etc/rc.d/rc.local 2.添加下面两行脚本, ...

  3. 天然气管道Gaz[POI2007]

    --BZOJ1034 题目描述 Mary试图控制成都的天然气市场.专家已经标示出了最好的天然气井和中转站在成都的地图.现在需要将中转 站和天然气井连接起来.每个中转站必须被连接到正好一个钻油井,反之亦 ...

  4. Windows PowerShell基本语法及常用命令

    PowerShell常用命令: 一 Get类 1.Get-Command : 得到所有PowerShell命令,获取有关 cmdlet 以及有关 Windows PowerShell 命令的其他元素的 ...

  5. Android学习(四)

    教材学习内容总结 图形和定制视图 硬件加速 Android APILevel14及其以上版本为目标的应用程序来说,硬件加速是默认可用的. 可通过android:hardwareAccelerated= ...

  6. Listener随笔

    [1]监听器简介   > Listener是JavaWeb中三大组件之一.Servlet.Filter.Listener   > 三大组件都有的共同特点,都需要实现一个接口,并在web.x ...

  7. Python从入门到精通之Forth!

    Python基本数据类型之列表 补充:range()方法 python2: range   立即创建 xrange  for循环的时候才一个一个创建 Python3: range     for循环的 ...

  8. Python Day 10

    阅读目录: 函数 函数的使用 函数的分类 函数的返回值 ##函数 ##函数的定义-----what?----什么是函数: # 函数:完成 特定 功能的代码块,作为一个整体,对其进行特定的命名,该名字就 ...

  9. C++解题报告 : 迭代加深搜索之 ZOJ 1937 Addition Chains

    此题不难,主要思路便是IDDFS(迭代加深搜索),关键在于优化. 一个IDDFS的简单介绍,没有了解的同学可以看看: https://www.cnblogs.com/MisakaMKT/article ...

  10. 2019.03.28 bzoj3597: [Scoi2014]方伯伯运椰子(01分数规划)

    传送门 题意咕咕咕有点麻烦不想写 思路: 考虑加了多少一定要压缩多少,这样可以改造边. 于是可以通过分数规划+spfaspfaspfa解决. 代码: #include<bits/stdc++.h ...