volatile和synchronized与lock的理解
volatile
特征:
a:可见性:一个线程修改了某个共享变量的值,其他线程能够立马得知这个修改。
b:禁止特定的处理器重排序。
volatile的内存语义:
1.当写一个volatile变量的时候,jmm会把本地内存中的共享变量刷新到主内存。
2.当读一个volatile变量的是时候,jmm会把线程本地内存的值设置为无效,然后从主内存中读取共享变量。
volatile的重排序有三个规则:
1.当第二个操作为volatile写的时候,第一个操作不管是什么,都不允许重排序。
2.当第一个操作为volatile读的时候,第二个操作不管是什么,都不允许重排序。
3.当第一个操作为volatile写的时候,第二个操作是volatile读的时候,不允许重排序。
除此以外的情况,都运行重排序。而重排序的实现是靠加入内存屏障来实现的。内存屏障时用来禁止特定的重排序的cpu指令。包括4中,loadload,store store,store load与load/store。load可以理解为读操作,store可以理解为写操作,举例说明,loadload是保证在第二个load和其他一系列操作之前要确保第一个load的读操作完成。store store是保证在第二个store及写操作之前,第一个store写操作对其他处理器可见。其中store load的开销最大,是个万能屏障,兼具其他三个屏障的功能。
synchronized和lock的底层实现和对比:
synchronized是通过jvm原生实现的,其中可以分为给代码块加锁,给方法加锁,给静态类加锁。给代码块加锁锁住的是加锁的对象,给方法加锁锁住的是对象实例,给静态类加锁锁住的是整个类。
jvm通过进入和退出monitor来实现代码块和方法的同步。其中给代码块加锁可以理解为在方法的入口和出口分别加入了monitorenter和monitorexit字节码指令来实现的。必须要保证有一个monitorenter对应一个monitorexit,进入到monitorenter就表示拿到了相应的锁。java1.6之前synchronized可以说是重量级锁,1.6之后对synchronized做出的优化使得synchronized没有那么重量级了,加入了锁粗化,自旋锁和自适应自旋,锁消除,轻量级锁,偏向锁。
锁粗化是对对一个代码块家了很多锁,由于要不停的进入和出去加大的开销,可以把一部分联系紧密的代码块合并为一个锁或者少量的锁,使锁的力度变粗。
锁消除是当代码块中有锁但是检测到不存在竞争没有必要加锁的时候就把锁去掉。
自旋锁:同步的时候阻塞会影响性能,挂起线程和恢复线程的操作都需要转入内核态来完成,这些操作给系统的并发性能带来的很大的压力。在很多共享数据的锁定状态之后持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得。如果物理机上不止一个处理器,能让两个或以上的线程同时并行执行,我们可以让后面请求锁的线程“稍等一下”,但是不放弃cpu,看看持有锁的线程是否很快就会释放锁。为了让线程等待,我们只需让线程执行一个等待,这就是自旋。自旋值默认是10。1.6中引入了自适应的自旋,如果前一个刚刚获得过锁,并且持有锁的线程还在进行中,那么虚拟机会认为下一次自旋也有可能成功,进而允许自旋等待更长时间。对于很少获得的锁,直接放弃自旋,避免资源浪费,直接挂起线程。
轻量级锁:轻量级锁是相对于重量级锁而言的,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。在进入代码块的时候,如果此同步对象没有被锁定,也就是锁标志位是01状态,虚拟机首先在当前线程的栈帧上建立一个锁记录(lock record),用于存储Mark world的拷贝,然后虚拟机将使用cas操作尝试将对象的Mark world更新指向lock record的指针。更新成功了那么该线程就拥有了锁,并且对象的锁标志位将装换为00,即表示此对象处于轻量级锁的状态。更新失败了,虚拟机首先检查Mark world是否指向lock record,是的话说明当前线程已经拥有了这个对象的锁,那就直接进去代码块继续执行,否则说明锁对象已经被其他线程抢占了。如果有两个以上的对象争用一个锁,那么轻量级锁不再有效,升级为重量级锁,锁状态变为10,mark word中存储的就是重量级锁的指针。
偏向锁:如果说轻量级锁是在无竞争的条件下使用cas操作去消除同步使用的互斥量,那么偏向锁就是在无竞争的条件下把整个同步都省掉,连cas操作都不做了。偏向的偏,意思就是如果获取了锁,下一个获取的话偏向由上一次获取它的线程来获取。当线程第一次获取到锁对象,状态改写为01,然后使用cas操作,把获取到锁的线程的id记录在mark word中,如果cas成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时,虚拟机都可以不在进行任何同步操作。当有另外一个线程去尝试获取这个锁时,偏向模式宣告结束。根据锁对象目前是否处于锁定的状态,撤销偏向后恢复到未锁定或轻量级锁定。
而lock是Java写的,基于aqs框架,需要显示的获取锁和释放锁,并且包含在try catch finally语句块里面,同样是可重入锁,lock还提供了比synchronized更强大的一些功能。主要包括三点:
1.可中断获取锁,获取锁的时候可以定时,如果过了这个时间还是没有获得锁,那么就改为做其他事情。
2.可以绑定多个条件。synchronized里面,如果用wait、notify的话,实现的是隐含的一个条件,如果要和多于一个的条件绑定的话需要再创建锁。而lock不需要,一个锁可以产生多个condition,只需要通过lock的newcondition方法即可。
3.可以实现公平锁。
volatile和synchronized与lock的理解的更多相关文章
- 线程、volatile与synchronized、Lock
目录 线程 1.概念: 2.线程生命周期: 3.线程调度 4.线程实现 4.1.实现方式 4.2.之间的区别: 5.线程安全 5.1.volatile与synchronized 5.1.synchro ...
- Java并发编程知识点总结Volatile、Synchronized、Lock实现原理
Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...
- volatile、synchronized、lock有什么区别,以及在哪些场景下使用哪种方式?
[转]JVM锁机制volatile/synchronized/lock 1.volatile实现原理 (1)聊聊并发(一)——深入分析Volatile的实现原理 --硬件级别锁实现,Lock前缀指令会 ...
- 从JMM透析volatile与synchronized原理,图文并茂
在面试.并发编程.一些开源框架中总是会遇到 volatile 与 synchronized .synchronized 如何保证并发安全?volatile 语义的内存可见性指的是什么?这其中又跟 JM ...
- synchronized和lock以及synchronized和volatile的区别
synchronized和volatile区别synochronizd和volatile关键字区别: 1. volatile关键字解决的是变量在多个线程之间的可见性:而sychronized关键字解决 ...
- java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解
一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工 ...
- 理解volatile与synchronized
用 volatile 修饰的变量可以保证线程的"可见性",也就是,任何线程修改了这个 volatile 修饰的值都会通知其他线程来主缓存中重新读取值. 下面通过例子加以说明: pu ...
- 剑指Offer——线程同步volatile与synchronized详解
(转)Java面试--线程同步volatile与synchronized详解 0. 前言 面试时很可能遇到这样一个问题:使用volatile修饰int型变量i,多个线程同时进行i++操作,这样可以实现 ...
- 详解synchronized与Lock的区别与使用
知识点 1.线程与进程 在开始之前先把进程与线程进行区分一下,一个程序最少需要一个进程,而一个进程最少需要一个线程.关系是线程–>进程–>程序的大致组成结构.所以线程是程序执行流的最小单位 ...
随机推荐
- sql添加列,删除列,修改列
有时候,当数据库里面有数据了,再到设计器里面删除列,就删不掉.只能用代码删除. alter table tableName drop column columnName 添加列 ) 修改列 ) --修 ...
- border使用小技巧
border-style 分类 dashed虚线类型 dotted 点线类型 double 双线类型 双线型量根实线的宽度和中间空白区域的间距有一定规律: 可以利用这个规律画出一些特殊的图案 代码如下 ...
- 纸壳CMS 2.3,正式加入商城功能
纸壳CMS发布了2.3版本,主要是添加了商城功能,强化产品功能.让您的网站轻松实现电子商务. 有关2.3版本的更多信息,请查看以下链接: https://github.com/SeriaWei/ZKE ...
- WPF 修改dev GridControl行背景色
<dxg:TableView.RowStyle> <Style TargetType="dxg:RowControl" > <Style.Trigge ...
- jQuery为DOM动态追加事件
处理一个列表绑定,因为是一个展示项目,没有使用复杂的插件,直接jsrender写了个模板,但是后面有一个操作按钮,去查看数据详情,想到了jquery使用on进行事件委托,然后就开搞 最初是这样写的: ...
- 清除clusternode
Import-Module FailoverClusters then clear-clusternode
- 8、insert、delete、update语句总结
insert常用语句 > insert into tb1 (name,age) values('tom',33); > insert into tb1 (name,age) values( ...
- vue.js 知识点(三)
---恢复内容开始--- vue和react相同,都是单项数据流,也就是只能从父组件流向子组件,但是因为根据引用的不同,子组件也是可以经过函数处理流向父组件的!这点跟react十分相似,但是也有不同: ...
- 木马APP的简单分析(Android Killer分析)
本文作者:三星s7edge 一.此贴目的:分析一个木马APP样本的行为.—————————————————————————————————————————————————-二.分析步骤及结果: 文件名 ...
- 20 行代码极速为 App 加上聊天功能
现在很多 App 都需要集成 IM 功能,今天就为大家分享一下集成 IM 基本功能的步骤.本文内容以 JMessage 为例.极光 IM ( JMessage ) = 极光推送 ( JPush ) + ...