Java并发编程原理与实战九:synchronized的原理与使用
一、理论层面
内置锁与互斥锁
修饰普通方法、修饰静态方法、修饰代码块
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 如何实现同步功能的一个视频学习总结,更加细节的深入原理可以参考下面两篇文章:
参考资料:
《java并发编程与实战》龙果学院
Java并发编程原理与实战九:synchronized的原理与使用的更多相关文章
- Java并发编程系列-(8) JMM和底层实现原理
8. JMM和底层实现原理 8.1 线程间的通信与同步 线程之间的通信 线程的通信是指线程之间以何种机制来交换信息.在编程中,线程之间的通信机制有两种,共享内存和消息传递. 在共享内存的并发模型里,线 ...
- Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析
相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Java并发编程(三)volatile域 Java并发编程(四)Java内存模型 Java并发编程(五)Concurr ...
- Java并发编程知识点总结Volatile、Synchronized、Lock实现原理
Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...
- 【Java并发编程之深入理解】Synchronized的使用
原文:https://blog.csdn.net/zjy15203167987/article/details/82531772 1.为什么要使用synchronized 在并发编程中存在线程安全问题 ...
- 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)
Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...
- 转:【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17199201 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访 ...
- 【Java并发编程】之七:使用synchronized获取互斥锁的几点说明
在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确 ...
- java并发编程学习: 阻塞队列 使用 及 实现原理
队列(Queue)与栈(Stack)是数据结构中的二种常用结构,队列的特点是先进先出(First In First Out),而Stack是先进后出(First In Last Out),说得通俗点: ...
- java并发编程的艺术(四)---ConcurrentHashMap原理解析
本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...
- Java 并发编程中使用 ReentrantLock 替代 synchronized 关键字原语
Java 5 引入的 Concurrent 并发库软件包中,提供了 ReentrantLock 可重入同步锁,用来替代 synchronized 关键字原语,并可提供更好的性能,以及更强大的功能.使用 ...
随机推荐
- Express搭建NodeJS项目
1.安装Node.js: 2.安装npm; 3.安装Express; 在本例中默认全局安装express 安装express生成器 如果没有安装express-generator或安装路径不对,会报以 ...
- Enterprise Library 1.1 参考源码索引
http://www.projky.com/entlib/1.1/Microsoft/Practices/EnterpriseLibrary/Caching/BackgroundScheduler.c ...
- beta发布的评论
1. 组名:飞天小女警 项目名:礼物挑选小工具 评价:对于我们学生来说,选礼物小工具相对来说新颖,小组添加了前十名热门礼物的推荐.发布到服务器上了,未来也有很多选择的空间可以做成礼物挑选手机app,也 ...
- 微信小程序 功能函数picker-view的弹出模态
<view class="list"> <form bindsubmit="formSubmit"> <view class=&q ...
- No module named 'MySQLdb' python3.6 + django 1.10 + mysql 无法连接
学习python 连接mysql数据库的时候遇到了问题 首先安装mysql: 工具栏 ===>file ==> default settings==>Project Interpre ...
- Windows系统下Log4Net+FileBeat+ELK日志分析系统问题总结
问题如下:1.FileBeat日志报 "dial tcp 127.0.0.1:5544: connectex: No connection could be made because the ...
- redis压力测试工具-----redis-benchmark
redis做压测可以用自带的redis-benchmark工具,使用简单 压测命令:redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 10000 压测需要一段 ...
- IE 低版本 透明度
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【刷题】BZOJ 2816 [ZJOI2012]网络
Description http://www.lydsy.com/JudgeOnline/upload/zjoi2012.pdf Solution 维护树上联通块的信息,支持动态加边删边 LCT 总共 ...
- Nginx 线上配置实例
1 /etc/nginx/nginx.conf,在主配置下设置 /etc/nginx/conf.d/*.conf user nginx;worker_processes 1; error_log /v ...