同步机制之一--Synchronized,以及此机制下的锁的本质和种类
Java中,为了实现同步的操作临界区,线程在执行临界区的代码时,需要获得某个对象的锁。本文介绍获得对象的锁的方法之一----Synchronized关键字。
Synchronized关键字的用法
Class Test {
....
Object o = new Object();
public synchronized test() { //第一种用法
....
}
public test_1 () {
synchronized (o) { //第二种用法
....
}
}
}
Synchronized关键字有两种用法,一种修饰方法,作用在调用此方法的对象;一种修饰代码块,在括号中指定作用的对象。在上面的例子中,在某个线程中创建Test对象 t ,在线程1调用 t.test() 则线程需要获取 t 的锁;调用 t.test_1() 线程则需要 t 持有的对象 o 的锁。
Synchronized机制下锁的本质
锁的本质实际上就是对象的头部几个bit的标志而已,根据这些标志不同,对象又分出了无锁(01),偏向锁(01),轻量级锁(00),重量级锁(10),锁可以从左至右逐渐升级,却不能降级。具体如下表格

由于 01 状态可以表示两种锁,因此 锁标志为01时,还要检查偏向锁标志,为1表示偏向锁,为0表示无锁。
为什么需要这么多种类的锁呢?JDK1.6(应该是)为了解决线程用Synchronized获取锁失败后必须阻塞等待的情况,因为这样效率太低了。下面介绍几种锁的机制。
偏向锁
对象初始的锁默认是偏向锁,可以通过XX: -UseBiasedLocing = false 放弃使用偏向锁,那么所有对象的默认锁就是轻量级锁。当一个对象是偏向锁时,对象头里会存储着此对象偏向的线程id的信息。一个线程获取某个对象的偏向锁的流程如下:

一个线程持有某个对象的偏向锁,并且受到竞争,偏向锁就有可能膨胀为轻量级锁,流程如下:

轻量级锁
轻量级锁由偏向锁膨胀而来,它的特点是获取轻量级锁失败的线程不会陷入阻塞。而是通过CAS的方式去获取锁,失败则重试,再次进行CAS操作去获取锁,也称自旋。CAS是一个原子操作,以后再总结。
如果是一个线程以及获得了某个对象的轻量级锁,还被其他线程不断竞争,轻量级锁就会膨胀为重量级锁。
获取轻量级锁的过程如下:

大概就是: 线程p的栈中有一块空间local record专门存放以经获取到的对象锁的信息。首先,将要目标对象的mark word拷贝进local record;然后对象的mark word部分就变为一个指针,指向displaced空间,更新锁标志、状态; 最后把local record的 owner 指针指向目标对象,表明已经获得这个对象的锁了。解锁,就是上述过程的反向操作。当然,这些操作是CAS方式进行的。
重量级锁
重量级锁是彻底的悲观锁,当一个线程获取某个对象的重量级锁失败时,线程便会阻塞,进入锁定池,等待这个锁被释放。当一个对象的锁变成了重量级锁,mark word便会成为一个指向 Mutex Lock(互斥量)的指针。
同步机制之一--Synchronized,以及此机制下的锁的本质和种类的更多相关文章
- Synchronized机制下偏向锁、轻量级锁、重量级锁的适用场景
上次总结了Synchronized机制下的锁的种类和原理,这次总结一下几种锁的适用场景. 偏向锁 一个线程获取某个对象的偏向锁的成本是很低的,只需把对象头的偏向线程id改为自己就好,如果偏向线程id已 ...
- java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader
1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...
- JVM锁机制之synchronized
概述: synchronized是java用于处理多线程同步的一个关键字,用于标记一个方法/代码块,使之成为同步方法/同步块. 用synchronized可以避免多线程处理时的竞态条件问题. 相关概念 ...
- (转载)JVM实现synchronized的底层机制
目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea.本文并不比较synchronized与Loc ...
- [转帖]B4. Concurrent JVM 锁机制(synchronized)
B4. Concurrent JVM 锁机制(synchronized) https://www.cnblogs.com/zlxyt/p/11050346.html 挺好的 感觉这个文章写的 不过想要 ...
- 并发编程的锁机制:synchronized和lock
1. 锁的种类 锁的种类有很多,包括:自旋锁.自旋锁的其他种类.阻塞锁.可重入锁.读写锁.互斥锁.悲观锁.乐观锁.公平锁.可重入锁等等,其余就不列出了.我们重点看如下几种:可重入锁.读写锁.可中断锁. ...
- java ->多线程_线程同步、死锁、等待唤醒机制
线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. l 我们通过一个案例,演示线 ...
- java面试-synchronized底层实现机制
一.synchronized的三种应用方式 1.修饰实例方法,锁是当前实例对象,进入同步代码前要获得当前实例的锁 /** * synchronized修饰实例方法,当前线程的锁是实例对象account ...
- C#中的WinForm的消息机制简述,及消息机制下Invoke,和BeginInvoke的使用和区别
在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate,至于委托的本质请参考我的另一随笔:对.net事件的看法. 一.为什么Control类提供了Invoke和Begin ...
随机推荐
- java - 数组与String的length方法问题
java数组没有length()方法,java数组有length属性: String有length()方法.
- Go组件学习——cron定时器
1 前言 转到Go已经将近三个月,写业务代码又找到了属于Go的条件反射了. 后置声明和多参数返回这些Go风格代码写起来也不会那么蹩脚,甚至还有点小适应~ 反而,前几天在写Java的时候,发现Java怎 ...
- python基础——元组(tuple)
Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. tuple1 = () tuple2 = ...
- 简单的JSP分页显示
1.mysql的limit关键字 (DAO) select * from tablename limit startPoint, numberPerPage; tablename 就是要分页显示的那张 ...
- php的中文字符
在使用substr截取字符窜的时候出现乱码的问题 一直任认为字符串是2个字节,直到多次才尝试才总算知道问题所在 php的utf-8字符是每个字符3个字节 而gbk字符是每个字节2个字符 单个字母和符号 ...
- vue.js主要内容
vue的主要内容 1.了解vue 2.vue开发环境的搭建和脚手架工具的使用 3.vue具体的指令和项目实战 1.了解vue 1.具备基础:html.css.js,模块化概念.ES6语法(简单即可) ...
- RocketMQ中Producer消息的发送
上篇博客介绍过Producer的启动,这里涉及到相关内容就不再累赘了 [RocketMQ中Producer的启动源码分析] Producer发送消息,首先需要生成Message实例: public c ...
- 传输层的TCP和UDP协议
作者:HerryLo 原文永久链接: https://github.com/AttemptWeb... TCP/IP协议, 你一定常常听到,其中TCP(Transmission Control Pro ...
- Hadoop 系列(一)—— 分布式文件系统 HDFS
一.介绍 HDFS (Hadoop Distributed File System)是 Hadoop 下的分布式文件系统,具有高容错.高吞吐量等特性,可以部署在低成本的硬件上. 二.HDFS 设计原理 ...
- 死磕JVM之类中各部分的加载顺序
话不多说,直接上代码: 1.通过new创建对象实例: 2.当对象中含有静态方法,且调用时: -- 调用父类静态方法: 总结: * 类中静态资源首次加载的时间是类中静态资源第一次被调用的时候或者该类的对 ...