Java并发编程之synchronized关键字
整理一下synchronized关键字相关的知识点。
在多线程并发编程中synchronized扮演着相当重要的角色,synchronized关键字是用来控制线程同步的,可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块,保证一个线程的变化(主要是共享变量的变化)被其他线程所看到,即保证可见性,可以替代volatile。
1、Synchronized具体表现形式
synchronized的实现和对象锁有关,Java中的每一个对象都可以作为锁,具体表现为以下三种形式:
- 修饰普通方法:作用于当前实例加锁,进入同步代码前要获得当前实例的锁;
public synchronized void method1()
{
// todo
}
- 修饰静态方法:作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁;
public static synchronized void method2()
{
// todo
}
- 修饰代码块:指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。锁是Synchonized括号里配置的对象。配置的对象分为以下三种情况:
1、实例对象
synchronized(this) {
// todo
}
2、类对象
synchronized(Demo.class) {
// todo
}
3、任意实例对象Object
String lock = “”;
synchronized(lock) {
// todo
}
需要注意的是:如果锁的是类对象的话,尽管new多个实例对象,但他们仍然是属于同一个类依然会被锁住,即线程之间保证同步关系。
2、Synchonized实现原理
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。同步代码块为显示同步,使用monitorenter 和monitorexit指令实现。同步方法为隐式同步,由方法调用指令读取运行时常量池中方法的 ACC_SYNCHRONIZED 标志来隐式实现。
public class SynchronizedDemo {
public static void main(String[] args) {
synchronized (SynchronizedDemo.class) { }
}
public synchronized void method() { }
}
先看下上面这段代码,包含一个同步代码块和一个同步方法。通过javap –v 命令查看编译后的class文件。

先来看下main方法,上图中第4、6、12句命令就是添加synchronized之后生成的。执行同步代码块之前要先执行monitorenter指令,退出和异常的时候执行monitorexit指令。其关键就是必须要对对象的监视器monitor进行获取,当线程获取monitor后才能继续往下执行,否则将会被阻塞在同步块和同步方法的入口处,同时添加到一个同步队列中。每个对象都存在着一个 monitor 与之对应,当 monitor 被线程持有后,它就处于锁定状态,其他线程不能访问。

从上图可以看出,method同步方法没有看到monitorenter和monitorexit指令,而是通过ACC_SYNCHRONIZED标识指明method是一个同步方法。方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor,然后再执行方法,方法完成(无论是正常完成还是非正常完成)时释放monitor。Synchronized先天具有重入性,在同一锁程中,线程不需要再次获取同一把锁。每个对象拥有一个计数器,当线程获取该对象锁后,计数器就会加一,释放锁后就会将计数器减一。
对象,对象监视器,同步队列以及执行线程状态之间的关系如下图:

3、Java对象头
java对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。如下:
实例变量:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。
填充数据:由于虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐,这点了解即可。
对象头:synchronized用的锁是存在Java对象头里的,主要结构是Mark Word 和 Class Metadata Address。当对象是数组时,会多一个Array length来存储数组的长度。
- Mark Word里默认存储对象的HashCode、分代年龄和锁标记位。32位JVM的Mark Word默认存储结构如下:

- Class Metadata Address存储了类型指针指向对象的类元数据,JVM通过这个指针确定该对象是哪个类的实例。
对象头的信息与对象自身定义的数据是没有关系的,在运行时,Mark Word里存储的数据会随着锁标志位的变化而变化。除了默认存储结构,还有可能变化成以下结构:
这部分照搬了《Java并发编程的艺术》书中的一段,这块的东西只是简单的过了一遍。
4、synchronized的优化
Java 6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。锁的状态总共有四种,无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁,锁可以升级但不能降级。
Java并发编程之synchronized关键字的更多相关文章
- Java 多线程并发编程之 Synchronized 关键字
synchronized 关键字解析 同步锁依赖于对象,每个对象都有一个同步锁. 现有一成员变量 Test,当线程 A 调用 Test 的 synchronized 方法,线程 A 获得 Test 的 ...
- Java并发编程之volatile关键字解析
一内存模型的相关概念 二并发编程中的三个概念 三Java内存模型 四深入剖析volatile关键字 五使用volatile关键字的场景 volatile这个关键字可能很多朋友都听说过,或许也都用过.在 ...
- Java并发编程之volatile关键字
大概是因为项目.业务的原因,工作上几乎还没有使用过多线程相关的功能,相关知识差不多都忘了,所以最近补一下基础. volatile用来修饰共享变量,volatile变量具有 synchronized 的 ...
- 并发编程之synchronized关键字
synchronized关键字 synchronized关键字最主要的三种使用方式的总结 1.修饰实例方法,作用于当前对象实例加锁,进入同步代码块前要获得当前对象实例的锁 2.修饰静态方法,作用于当前 ...
- Java 并发编程之volatile关键字解析
摘录 1. 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执 ...
- Java并发编程之synchronized
在Java编程中,为了保证线程安全,有3种不同的思路1.互斥同步:包括synchronized和lock等. 2.非阻塞同步:如AtomicInteger的increaseAndGet()方法等. 3 ...
- Java并发编程之CAS
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...
- Java并发编程之CAS二源码追根溯源
Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...
- Java并发编程之CAS第一篇-什么是CAS
Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl.从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是<凯哥 ...
随机推荐
- Python开发——数据类型【列表】
列表的定义 中括号[]内以逗号分隔开,按照索引,存放各种数据类型,每个位置代表一个元素 list_t = ['张三','Lucy',123] print(list_t) # ['张三', 'Lucy' ...
- python 实现 Fortran的读取10*0以及换行读问题
思路,用read来全部读取,然后替换带*的元素来解决.代码如下 import numpy as np import re inf = open('SF.usr') title = inf.readli ...
- 《Miracle_House团队》第一次作业:团队亮相
Our Team:Miracle_House part 1 团队成员组成: NO.1 汝春瑞 201571030125 (组长) Style:乐观开朗,认真踏实,责任心强,还有就是爱笑.随和 ...
- Android 多线程编程
Android 多线程编程 //1.多线程 进程:操作系统的多道程序 线程:同一个程序的多条路径 //2.创建多线程程序 创建一个类extends Thread 重写run方法 在main方法中创建对 ...
- 【微信小程序开发】页面配置
app下的app.json文件是全局配置. app下的每一个page中,也可以配置.json文件. page中配置的内容是对应app中window配置项下的内容. page中的配置将覆盖window中 ...
- HNOI 2018 简要题解
寻宝游戏 毒瘤题. 估计考试只会前30pts30pts30pts暴力然后果断走人. 正解是考虑到一个数&1\&1&1和∣0|0∣0都没有变化,&0\&0& ...
- input实现图片或视频上传(样式+代码)
背景:vue/element.ui 1..html: <div v-show="recordForm.resourceType==1"> <el-form-ite ...
- shp文件和地理数据库文件的区别
存储文件结构不同.所能进行的计算也不同. https://blog.csdn.net/lucahan/article/details/51761610 对数据库操作更快更方便,如何证明?尤其是数据量比 ...
- 卷积(转自wiki百科)
维基百科,自由的百科全书 图示两个方形脉冲波的卷积.其中函数 "g" 首先对 反射,接着平移 "t" ,成为 .那么重叠部份的面积就相当于 "t& ...
- Pycharm2018的激活方法或破解方法
1.授权服务器激活 优点:方便快捷 缺点:激活的人数多了就容易被封杀,所以可能经常需要去激活 选择License server激活,然后填入: idea.qmanga.com或http://xidea ...