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.线程与进程 在开始之前先把进程与线程进行区分一下,一个程序最少需要一个进程,而一个进程最少需要一个线程.关系是线程–>进程–>程序的大致组成结构.所以线程是程序执行流的最小单位 ...
随机推荐
- 代码审查清单 Code Review
代码审查清单 常规项 代码能够工作么?它有没有实现预期的功能,逻辑是否正确等. 所有的代码是否简单易懂? 代码符合你所遵循的编程规范么?这通常包括大括号的位置,变量名和函数名,行的长度,缩进,格式和注 ...
- 编写高质量代码改善C#程序的157个建议——建议122:以<Company>.<Component>为命名空间命名
建议122:以<Company>.<Component>为命名空间命名 建议以<Company>.<Component>为程序集命名,比如Microso ...
- centos 7防火情配置
查看版本 firewall-cmd --version 2 查看指定端口是否开放 firewall-cmd --query-port=端口号/tcp 3 开放指定端口(--permanent表示永久, ...
- JavaScript - this详解 (三)
闭包 this 执行上下文决定了变量作用域 而闭包,它其实是一种决策,是一种模式,让我们可以灵活的改变变量作用域. 按惯例,上栗子 var global = 'global';function out ...
- opencv——播放视频
#include "stdafx.h" #include <opencv2\opencv.hpp> #include <iostream> #include ...
- Tomcat 警告:consider increasing the maximum size of the cache
最近在Tomcat8上导入原本Tomcat6的项目,报了以下错误:Tomcat 警告:consider increasing the maximum size of the cache. 这是因为to ...
- 自己动手设计并实现一个linux嵌入式UI框架
一直以来都是使用现成的UI框架,如微软的window.QT等,因为它有各种控件(如button.window.edit等)都已经封装实现好了.我们只要拿来用就是了,也一直认为它很神圣,没有深入了解它背 ...
- SQL Server 2008R2 附件数据库问题记录
在Sql Server 2008 R2里附加数据库时弹出xxx.mdf拒绝访问的错误 详细错误信息如下: TITLE: Microsoft SQL Server Management Studio-- ...
- PT, BPT, VCM
- VCM可以理解为BPT与PPM之间的MIS,并没有比BPT效果好很多 - BPT, VCM这类算法的主要作用是加快caustics的收敛,对indirect diffuse没有很明显的加速 - i ...
- UML uml建模工具
UML建模工具 一.UML的概念: 参考百度百科: https://baike.baidu.com/item/%E7%BB%9F%E4%B8%80%E5%BB%BA%E6%A8%A1%E8%AF%AD ...