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: 原子性:所谓原子性 ...
随机推荐
- linux 系统运维工具13款
1. 查看进程占用带宽情况 - Nethogs Nethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽. 下载:http://sourceforge.net/projects/ ...
- iOS CALayer总结——图层几何
最近看了一下关于图层和动画的内容,所以写了一份总结,算是对这些内容的汇总吧,都是一些简单的基础知识,不知道大家都了不了解. 除了和用户的交互之外,图层的很多属性和视图基本上都是一样的,今天就先从CAL ...
- Thymeleaf 模板
Thymeleaf 模板布局 th:fragment.th:replace.th:insert.th:remove th:fragment 模板布局 模板片段说明 模板中,经常希望从其他模板中包含⼀ ...
- 一个让Java事半功倍的反射库
在Java和Android中,我们常常会使用反射来达到一些兼容的目的.Java原生提供的反射很是麻烦,使用起来很是不方便.比如我们想要调UserManager的静态方法get,使用原生的实现如下 tr ...
- MVC-Application
Application简述(不如Cache) 在asp.net环境下,Application对象来自HttpApplictionStat类.它可以在多个请求.连接之间共享公用信息,也可以在各个请求连接 ...
- Mysql 中完善的帮助命令
Mysql 中完善的帮助命令 Mysql 中的帮助系统很完善,很多操作都可以通过命令行直接获得帮助,如下示例: Mysql 命令行帮助 [root@mysql1 mydata1]# mysql -S ...
- Computer Vision_33_SIFT:A novel coarse-to-fine scheme for automatic image registration based on SIFT and mutual information——2014
此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...
- C++——多态实现原理分析
前言 虚函数执行速度要稍慢一些.为了实现多态性,每一个派生类中均要保存相应虚函数的入口地址表,函数的调用机制也是间接实现.所以多态性总是要付出一定代价,但通用性是一个更高的目标. 实验环境 Windo ...
- 【OF框架】使用原生Sql查询返回实体
使用原生Sql查询为Entity Framework Core自身的能力,本处描述如何在框架中调用该能力. 框架代码如下: (IoCHelper.Resolve<IDbContextCore&g ...
- JDBC终章- 使用 DBUtils实现增删查改- C3P0Utils数据源/QueryRunner runner连接数据源并执行sql
JDBC终章- 使用 DBUtils实现增删查改 1.数据库结构 Create Table CREATE TABLE `user` ( `id` ) NOT NULL AUTO_INCREMENT, ...