4.2 synchronized补充
时间:2022-07-25
本文章向大家介绍4.2 synchronized补充,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一、其他锁的概念(这个其他相对于第4节而言)
1. 锁的粗化
public class LockAppend {
Object object1 = new Object();
public void method() {
synchronized (object1) {
System.out.println("No1");
}
synchronized (object1) {
System.out.println("No2");
}
synchronized (object1) {
System.out.println("No3");
}
}
}
对于一个方法而言, 里面加了三把锁, 这样是没有任何意义的. 所以可以将其进行粗化处理
public class LockAppend {
Object object1 = new Object();
public void method() {
synchronized (object1) {
System.out.println("No1");
System.out.println("No2");
System.out.println("No3");
}
}
}
2. 锁的消除
public class LockAppend {
public void method1(){
Object object2 = new Object();
synchronized (object2) {
// ...
System.out.println("");
}
}
}
在方法里这样加锁是没有任何意义的.
因为, object2这个变量没有线程都是独有的, 不可能被其他线程访问到. 这样加锁没有任何一意义, 所以把锁去掉, 也就是消除.
3. 从jvm角度出发, 对Synchronized的优化
- 锁的膨胀升级, 这是一个不可逆的过程. 就是从无锁--->偏向锁--->轻量级锁--->重量级锁
- 锁的粗化
- 锁的消除
- 自旋锁
二. 线程的逃逸分析
使用逃逸分析,编译器可以对代码做如下优化:
一、同步省略。如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。
二、将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会逃逸,对象可能是栈分配的候选,而不是堆分配。
三、分离对象或标量替换。有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。
是不是所有的对象和数组都会在堆内存分配空间?
不一定
在Java代码运行时,通过JVM参数可指定是否开启逃逸分析, -XX:+DoEscapeAnalysis : 表示开启逃逸分析 -XX:-DoEscapeAnalysis : 表示关闭逃逸分析。从jdk 1.7开始已经默认开启逃逸分析,如需关闭,需要指定-XX:-DoEscapeAnalysis
关于逃逸分析的案例论证见Git课程源码
public class T0_ObjectStackAlloc {
/**
* 进行两种测试
* 关闭逃逸分析,同时调大堆空间,避免堆内GC的发生,如果有GC信息将会被打印出来
* VM运行参数:-Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
*
* 开启逃逸分析
* VM运行参数:-Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
*
* 执行main方法后
* jps 查看进程
* jmap -histo 进程ID
*
*/
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 500000; i++) {
alloc();
}
long end = System.currentTimeMillis();
//查看执行时间
System.out.println("cost-time " + (end - start) + " ms");
try {
Thread.sleep(100000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
private static TulingStudent alloc() {
//Jit对编译时会对代码进行 逃逸分析
//并不是所有对象存放在堆区,有的一部分存在线程栈空间
TulingStudent student = new TulingStudent();
return student;
}
static class TulingStudent {
private String name;
private int age;
}
}
- [译]Laravel 5.0 之目录结构与命名空间
- Python机器学习的练习六:支持向量机
- [译]Laravel 5.0 之路由缓存
- [译]Laravel 5.0 之 表单验证类 (Form Requests)
- 如何在Python中保存ARIMA时间序列预测模型
- Laravel 5.0 发布, 海量新特性!!
- Python中的白噪声时间训练
- Python机器学习的练习五:神经网络
- 在Python中如何差分时间序列数据集
- 将Keras权值保存为动画视频,更好地了解模型是如何学习的
- TensorFlow:如何通过声音识别追踪蝙蝠
- Python机器学习的练习四:多元逻辑回归
- Python机器学习的练习三:逻辑回归
- 什么?!只用30行代码就能创建一个JavaScript的神经网络?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python 如何使用 HttpRunner 做接口自动化测试
- Python 爬虫时,高版本 App 如何进行抓包?
- 使用 shell-operator 实现 Operator
- 我们是如何用 K8S 搞定1000个应用的测试环境
- 关于Python 3.9,那些你不知道的事
- urllib, urllib2, urllib3 都是小弟弟
- 使用 Kustomize 定制 Helm Chart
- 装逼篇 | 抖音超火的九宫格视频是如何生成的,Python 告诉你答案
- 最全总结 | 聊聊 Python 数据处理全家桶(Mysql 篇)
- 6个提升效率的pandas小技巧
- 如何用 Python 让微博热搜榜动起来
- 如何用 Python 让微博热搜榜动起来
- 漫画:什么是 “抽象工厂模式” ?
- 5个很常用的CSS3网页小实例
- 收藏!!!学习Matplotlib看这一份笔记就够了!