同步机制之一--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(互斥量)的指针。
最新文章
- python网络编程-socket编程
- linux用命令删除重复行
- linux进程间通信概述
- Mysql一主多从和读写分离配置简记
- Ubuntu 安装 Courier New字体
- 一个奇怪的编码 big5-hkscs
- html5新增操作类名方式 classList
- php 实现同一个账号同时只能一个人登录
- Highcharts属性介绍
- TJOI2015 day2解题报告
- CentOS下 elasticsearch集群安装
- ffmpeg 时间戳处理
- 向MIP开源项目提交Issues
- 密码疑云 (3)——详解RSA的加密与解密
- 从零开始单排学设计模式「UML类图」定级赛
- 手把手教你解析Resources.arsc
- 使用sqlite3解决IDEA中SVN更新提示cleanup却无法cleanup的问题
- oracle in 函数
- hadoop old API CombineFileInputFormat
- win7安装docker报错:error during connect: Get http ..... the system cannot find the file specified