synchronized的底层原理?
最近更新的XX必备系列适合直接背答案,不深究,不喜勿喷。
你能说简单说一下synchronize吗?
可别真简单一句话就说完了呀~
参考回答:
synchronize是java中的关键字,可以用来修饰实例方法、静态方法、还有代码块;主要有三种作用:可以确保原子性、可见性、有序性,原子性就是能够保证同一时刻有且只有一个线程在操作共享数据,其他线程必须等该线程处理完数据后才能进行;可见性就是当一个线程在修改共享数据时,其他线程能够看到,保证可见性,volatile关键字也有这个功能;有序性就是,被synchronize锁住后的线程相当于单线程,在单线程环境jvm的重排序是不会改变程序运行结果的,可以防止重排序对多线程的影响。
补充:我们来看一下上边这个回答,其中有好几个部分可以继续延伸,这里指的延伸就是面试官可以再继续问你的问题。
延伸一:java内存模型的三大特性,或者是说一下java内存模型,或者是synchronize跟java内存模型有什么关系吗?
首先补充为何会问到java内存模型,因为Synchronize的三种作用其实就是java内存模型保证的,再就是这个问题可能单独就蹦到考察java内存模型(JMM)上了。
1、什么是java内存模型:java虚拟机规范中定义了java内存模型是用来屏蔽各种硬件和操作系统间内存的差异,来实现java程序在各平台下并发一致性,再就是,java内存模型并不是真实存在的,他只是一种抽象概念,定义了线程和主内存之间的抽象关系,也就是线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存存储了该线程共享变量的副本。
2、java内存模型的三大特性:java内存模型有三大特性,原子性、可见性、有序性。
原子性:要么执行,要么不执行,主要使用互斥锁Synchronize或者lock来保证操作的原子性;
可见性:在变量修改后将新值同步回主内存,主要有两种实现方式,一是volatile,被volatile修饰的变量发生修改后会立即刷新到主内存;二是使用Synchronize或者lock,当一个变量unlock之前会将变量的修改刷新到主内存中;
有序性:在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序不会影响单线程的执行结果,却会影响多线程并发执行的正确性。主要有两种方式确保有序性:volatile 和 Synchronize 关键字,volatile是通过添加内存屏障的方式来禁止指令重排序,也就是重排序是不能把后面的指令放到内存屏障之前执行;Synchronize是保证同一时刻有且只有一个线程执行同步代码,类似于串联顺序执行代码。
延伸二:你了解先行发生原则(happens-before)吗?
为什么会出现先行发生原则:从上边我们也能看到,如果java内存模型中所有的有序性都要靠volatile和Synchronize来实现的话,那么是非常繁琐的,所以j就出现这么一个《先行发生原则》,用来判断数据是否存在竞争、线程是否安全的重要依据。
参考回答:
先行发生原则是java内存模型用来定义两个操作之间的偏序关系。比如说A操作先发生于B操作,那么在B操作发生之前,A操作修改了内存中的共享变量,那么就会被B操作察觉到。
先行发生原则其中包含8种规则,比如:程序员次序规则,volatile变量规则,线程的启动、中止、中断等规则。
如果再问到能简单介绍一下你说的这几个规则吗?一般不会问这么细的,了解即可。
程序员次序规则:在一个线程内,在程序前面的操作先行发生于后面的操作。
volatile变量规则:对一个 volatile 变量的写操作先行发生于后面对这个变量的读操作。
线程启动规则:Thread 对象的 start() 方法调用先行发生于此线程的每一个动作。
线程加入规则:Thread 对象的结束先行发生于 join() 方法返回。
线程中断规则:对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过 interrupted() 方法检测到是否有中断发生。
延伸三:volatile的作用,volatile跟Synchronize的区别
补充:如果上边不答到volatile,可能会跳过这个问题,但是多吹点说不定工资高点。
参考回答:
volatile的作用:volatile关键字主要作用是确保可见性跟有序性,当一个共享变量被volatile修饰,如果一个线程修改了这个共享变量,那么其他线程就会立马可知,强制刷新到主内存。
volatile跟Synchronize的区别:
- volatile只能作用域变量,Synchronize可作用域变量、方法、类、同步代码块等;
- volatile只能保证可见性和有序性,不能保证原子性,Synchronize三者都可以保证。
- volatile不会造成线程阻塞,Synchronize可能会造成线程阻塞。
- 在性能方面synchronized关键字是防止多个线程同时执行一段代码,会影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized。
延伸四:你能说说你刚刚提到的重排序吗?
你是否想过,重排序为什么会对多线程产生影响?
参考回答:
重排序是编译器和处理器为了优化程序性能而对指令进行重新排序的一种手段。重排序可以保证最终执行的结果是与程序顺序执行的结果一致,并且只会对不存在数据依赖性的指令进行重排序,重排序在单线程下对最终执行结果是没有影响的,但是在多线程下就会存在问题。
举个例子:
int a = 1;
int b = 2;
int c = a*b;
如上,a与c之间存在数据依赖关系,所以c不能排到A的前面,同时b与c之间也存在数据依赖关系,所以,c也不能排到B的前面,但是a与b之间是不存在数据依赖关系的,所以a与b之间是可以进行重排序的,但是无论怎么重排序都是不会影响到c的值。
但是在多线程中就不一样了,如下代码:
class Test{
/** 我是变量a **/
int a = 0;
/** 我是用来标记变量a是否被写入 **/
boolean flag = false;
/** 我是写操作 **/
public void writer(){
a = 1; /** 第1步 **/
flag = true; /** 第2步 **/
}
/** 我是读操作 **/
public void reader(){
if(flag){ /** 第3步 **/
int i = a * a; /** 第4步 **/
......
}
}
}
flag是一个变量,用来表示变量a是否已被写入。这里假设有两个线程A和B ,A线程首先执行writer()方法,随后线程B执行reader()方法。线程B在执行操作第4步的时候,能否看到线程A在操作共享变量a的写入呢?
答案是:在多线程的情况下,不一定能看到;
由于操作1和操作2没有数据依赖关系,编译器和处理器可以对这两个操作重排序;同样,操作3和操作4没有数据依赖关系,编译器和处理器也可以对这两个操作重排序。
具体细节可以看一下这篇文章,了解一下重排序对多线程的影响:https://blog.csdn.net/zhushuai1221/article/details/51491578
你能说一下Synchronize底层原理吗?
参考回答:
synchronized的底层原理是跟monitor有关,也就是视图器锁,每个对象都有一个关联的monitor,当Synchronize获得monitor对象的所有权后会进行两个指令:加锁指令monitorenter跟减锁指令monitorexit。
monitor里面有个计数器,初始值是从0开始的。如果一个线程想要获取monitor的所有权,就看看它的计数器是不是0,如果是0的话,那么就说明没人获取锁,那么它就可以获取锁了,然后将计数器+1,也就是执行monitorenter加锁指令;monitorexit减锁指令是跟在程序执行结束和异常里的,如果不是0的话,就会陷入一个堵塞等待的过程,直到为0等待结束。
最后
博客地址:https://www.cnblogs.com/niceyoo
如果觉得这篇文章有丶东西,不放关注一下我,关注是对我最大的鼓励~
18年专科毕业后,期间一度迷茫,最近我创建了一个公众号用来记录自己的成长。
synchronized的底层原理?的更多相关文章
- 天天用Synchronized,底层原理是个啥?
作者:liuxiaopeng https://www.cnblogs.com/paddix/p/5367116.html Synchronized 的基本使用 Synchronized 的作用主要有三 ...
- synchronized底层原理
synchronized底层语义原理 Java 虚拟机中的同步(Synchronization)基于进入和退出管程(Monitor)对象实现. 在 Java 语言中,同步用的最多的地方可能是被 syn ...
- Java程序员必会Synchronized底层原理剖析
synchronized作为Java程序员最常用同步工具,很多人却对它的用法和实现原理一知半解,以至于还有不少人认为synchronized是重量级锁,性能较差,尽量少用. 但不可否认的是synchr ...
- Synchronized之二:synchronized的实现原理
Java提供了synchronized关键字来支持内在锁.Synchronized关键字可以放在方法的前面.对象的前面.类的前面. 当线程调用同步方法时,它自动获得这个方法所在对象的内在锁,并且方法返 ...
- Java多线程和并发(八),synchronized底层原理
目录 1.对象头(Mark Word) 2.对象自带的锁(Monitor) 3.自旋锁和自适应自旋锁 4.偏向锁 5.轻量级锁 6.偏向锁,轻量级锁,重量级锁联系 八.synchronized底层原理 ...
- synchronized的底层实现原理
转自:http://www.cnblogs.com/paddix/p/5367116.html 如果对上面的执行结果还有疑问,也先不用急,我们先来了解Synchronized的原理,再回头上面的问题就 ...
- 基础篇:详解锁原理,volatile+cas、synchronized的底层实现
目录 1 锁的分类 2 synchronized底层原理 3 Object的wait和notify方法原理 4 jvm对synchronized的优化 5 CAS的底层原理 6 CAS同步操作的问题 ...
- Java并发编程:Synchronized及其实现原理
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
- synchronized 与 volatile 原理 —— 内存屏障的重要实践
单例模式的双重校验锁的实现: 第一种: private static Singleton _instance; public static synchronized Singleton getInst ...
随机推荐
- 已经编译安装的nginx/tenginx编译增加新模块
只适用于自行编译安装的nginx配置 业务变更带来的Nginx增加模块需求 由于业务从php转为go开发,需要用到Http2的协议.这种协议在Nginx上需要http_v2_module这个模块的支持 ...
- 推动中国制造升级,汽车装配车间生产流水线3D可视化
前言 随着<中国制造2025>的提出,制造业迎来了全新的发展机遇.更多的企业将制造业信息化技术进行广泛的应用,如 MES 系统.数字孪生以及生产管理可视化等技术的研究应用,已经成为社会各界 ...
- python数据分析01准备工作
第1章 准备工作 1.1 本书的内容 本书讲的是利用Python进行数据控制.处理.整理.分析等方面的具体细节和基本要点.我的目标是介绍Python编程和用于数据处理的库和工具环境,掌握这些,可以让你 ...
- 7. 组合你的UI
1. UI布局关键概念 一个组合应用UI的根节点被称作Shell,一般只有一个Shell.Shell作为应用的主页,包含一个或者多个域.域是内容占位符,可以包含一个或者多个View.有很多控件可以作为 ...
- php判断手机浏览器和pc浏览器
<?php public function is_mobile(){ // returns true if one of the specified mobile browsers is det ...
- Effective Modern C++ ——条款2 条款3 理解auto型别推导与理解decltype
条款2.理解auto型别推导 对于auto的型别推导而言,其中大部分情况和模板型别推导是一模一样的.只有一种特例情况. 我们先针对auto和模板型别推导一致的情况进行讨论: //某变量采用auto来声 ...
- 应对告警风暴,Cloud Alert 实现告警风暴智能降噪
前言 睿象云前段时间发表了一篇< Zabbix 实现电话.邮件.微信告警通知的实践分享>的技术文章.它帮助我们非常轻松地支持了各种告警通知方式,但是存在一个严重的问题,我们经常接到各种相类 ...
- 字符串匹配算法之Sunday算法(转)
字符串匹配算法之Sunday算法 背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是Ω(m*n),也就是达到了字符串匹配效率的下限.于是后来人经过研究 ...
- rbd的数据在哪里
创建一个rbd [root@mytest ~]# rbd create test1 --size 4000 查看rbd信息 [root@mytest ~]# rbd info test1 rbd im ...
- SpringSecurity之认证
SpringSecurity之认证 目录 SpringSecurity之认证 1. 盐值加密 1. 原理概述 2. 使用说明 1. 加密 2. 认证 1. 页面成功跳转的坑 2. 使用验证码校验的坑 ...