synchronized的原理与使用
理论层面:
内置锁与互斥锁
修饰普通方法、修饰静态方法、修饰代码块
demo如下:
package com.roocon.thread.t3;
public class Sequence {
private static int value;
// synchronized放在普通方法上,内置锁就是当前方法的实例
public synchronized int getNext(){
return value++;
}
// synchronized修饰静态方法,内置锁就是当前的Class字节码对象Sequence.class
public static synchronized int getPrevious(){
return value--;
}
public int xx(){
// synchronized修饰静态代码块,则锁的是任意一个对象
/*
synchronized (this){ }
synchronized (Integer.valueOf(value)) { }
synchronized (Sequence.class) { }
*/
synchronized (Sequence.class) {
if (value > 0) {
return value;
}else {
return -1;
}
}
}
public static void main(String[] args) {
Sequence sequence = new Sequence();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
jvm层面:

查看xx方法同步代码块字节码:

查看同步方法字节码:

任何对象都可以作为锁,那么锁信息又存在对象的什么地方呢?
存在对象头中。
对象头中的信息:
Mark Word
Class Metadata Address 类的类型地址
Array Length
1.偏向锁:
每次获得锁和释放锁会浪费资源(消耗时间),很多情况下,竞争锁不是由多个线程,而是由一个线程在使用。线程在获取锁时,会依据对象头Mark word信息进行判断执行。
对象头Mark word中会保存如下信息:
线程id
Epoch
对象的分代年龄信息
是否是偏向锁
锁标志位
偏向锁在获取锁之后,如果没有竞争,也就是一直是这个线程在获取锁,那么当这个线程第二次再来进入该方法时,不需要再去获取锁了,也不需要释放锁,这样,就节省了大量的获取锁释放锁的资源。那么,什么时候会释放锁呢?只有当存在竞争时,才会去释放锁。
偏向锁适用于什么场景?
只有一个线程在访问同步代码块的场景。
2.轻量级锁:可以同时让多个线程进入同步代码块。自旋锁就是轻量级锁。
轻量级锁是如何加锁的?
在线程执行同步代码块之前,jvm会先在当前线程的栈帧中创建用于存储锁记录的存储空间。
(栈帧是什么?虚拟机栈中存储的是一个一个的栈帧,栈帧中存储了方法的执行信息,每个方法都会伴随着栈帧的进栈和出栈)
然后呢,并将对象头中的mark word复制到锁记录中。然后呢,开始竞争锁就可以了。竞争成功之后,markword就改变了,会将锁标志位改成轻量级锁。接着,开始执行同步体。
另外一个线程也想获得该锁。同样,它也将对象头中的mark word复制到锁记录中,它发现已经被其他线程获得了锁,所以它修改不成功。于是,它就不停的去修改,不停的失败,直到第一个线程把这个锁释放了,它就可以修改成功了。刚才这一个过程,就是所谓的自旋锁。
3.重量级锁
什么是重量级锁?就是,这个线程获得锁进入之后,其他线程必须在外面等待。synchronized就是重量级锁。
synchronized的原理与使用的更多相关文章
- synchronized实现原理
线程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同操作共享数据.因此为了解决这个问题,我们可能需要这样一个方案, ...
- 深入理解Java并发之synchronized实现原理
深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...
- Java并发编程原理与实战九:synchronized的原理与使用
一.理论层面 内置锁与互斥锁 修饰普通方法.修饰静态方法.修饰代码块 package com.roocon.thread.t3; public class Sequence { private sta ...
- 深入理解并发编程之----synchronized实现原理
版权声明:本文为博主原创文章,请尊重原创,未经博主允许禁止转载,保留追究权 https://blog.csdn.net/javazejian/article/details/72828483 [版权申 ...
- Java精通并发-synchronized关键字原理详解
关于synchronized关键字原理其实在当时JVM的学习[https://www.cnblogs.com/webor2006/p/9595300.html]中已经剖析过了,这里从研究并发专题的角度 ...
- Java多线程和并发(八),synchronized底层原理
目录 1.对象头(Mark Word) 2.对象自带的锁(Monitor) 3.自旋锁和自适应自旋锁 4.偏向锁 5.轻量级锁 6.偏向锁,轻量级锁,重量级锁联系 八.synchronized底层原理 ...
- synchronized实现原理及其优化-(自旋锁,偏向锁,轻量锁,重量锁)
1.synchronized概述: synchronized修饰的方法或代码块相当于并发中的临界区,即在同一时刻jvm只允许一个线程进入执行.synchronized是通过锁机制实现同一时刻只允许一个 ...
- synchronized底层原理
synchronized底层语义原理 Java 虚拟机中的同步(Synchronization)基于进入和退出管程(Monitor)对象实现. 在 Java 语言中,同步用的最多的地方可能是被 syn ...
- synchronized运行原理以及优化
线程安全问题 线程不安全: 当多线程并发访问临界资源时(可共享的对象),如果破坏原子操作,可能会造成数据不一致. 临界资源:共享资源(同一对象),一次仅允许一个线程使用,才可以保证其正确性. 原子操作 ...
- synchronized的原理
synchronized的使用 synchronized是一个java中的关键字,是基于JVM层面的,用于保证java的多线程安全,它具有四大特性,可用于完全替代volatile: 原子性:所谓原子性 ...
随机推荐
- awk 条件及循环语句和字符串函数
条件语句 if(条件表达式) 动作1 else if(条件表达式) 动作2 else 动作3 循环语句: while循环: while(条件表达式) 动作 do while循环: do 动作 whil ...
- Go数据类型之基本数据类型
不想沦为芸芸众生的人只需做一件事,便是对自己不再散漫:他应当听从良知的呼唤:“成为你自己!” ---尼采 1.整型 有符号整数类型:int8.int16.int32和int64 无符号整数类型:uin ...
- Django:CSRF(Cross-request forgery)跨站请求伪造
一.CSRF是什么 二.CSRF攻击原理 三.CSRF攻击防范 一.CSRF是什么 CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Atta ...
- Centos 6.x开机启动流程
Centos 6.x开机启动流程 BIOS(COMS)检查 加载Bios,bios包含所有硬件信息(CPU,内存,硬盘,时钟,鼠标键盘等等) 读MBR 硬盘上第0磁道第一个扇区被称为MBR(maste ...
- linux网络编程之socket编程(八)
学习socket编程继续,今天要学习的内容如下: 先来简单介绍一下这五种模型分别是哪些,偏理论,有个大致的印象就成,做个对比,因为最终只会研究一个I/O模型,也是经常会用到的, 阻塞I/O: 先用一个 ...
- php守护进程创建和简要分析
守护进程可 由系统启动脚本 /etc/rc.local crontab任务, 用户shell 方式运行 具体概念可参考c的 进程守护化基本步骤 1.创建子进程,终止父进程 (pcntl_fork,ex ...
- 为RIDE创建桌面快捷方式
问题场景:默认情况下,RIDE的图标不是自动创建的,需要手动添加. 解决方法: 在桌面上新建"快捷方式" 目标对象的位置:C:\Python27\python2.exe - ...
- java疑问
1. new String("abc")究竟创建几个对象? 答: 一个或两个, 如果常量池中原来有"abc", 那么只创建一个对象; 如果常量池中原来没有&qu ...
- CSS float详解
前言:在我们写CSS样式的时候,float,position,display,overflow这几个关键字用得比较多. 弄清楚他们之间的原理,我们可以更高效的写出我们想要的布局. 作者:Ry-yuan ...
- js 实现多文件批量下载
关于兼容性问题: <a href="xxx.docx" target='_blank'></a> 下载文件时,这种写法是没有兼容性问题:但是下载图片时,IE ...