前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4.2 synchronized补充

4.2 synchronized补充

作者头像
用户7798898
发布2020-09-27 17:03:42
3250
发布2020-09-27 17:03:42
举报

一、其他锁的概念(这个其他相对于第4节而言)

1. 锁的粗化

代码语言:javascript
复制
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");
        }
    }
}

对于一个方法而言, 里面加了三把锁, 这样是没有任何意义的. 所以可以将其进行粗化处理

代码语言:javascript
复制
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. 锁的消除

代码语言:javascript
复制
public class LockAppend {
    public void method1(){
        Object object2 = new Object();
        
        synchronized (object2) {
            // ...
            System.out.println("");
        }
    }
}

在方法里这样加锁是没有任何意义的.

因为, object2这个变量没有线程都是独有的, 不可能被其他线程访问到. 这样加锁没有任何一意义, 所以把锁去掉, 也就是消除.

3. 从jvm角度出发, 对Synchronized的优化

  1. 锁的膨胀升级, 这是一个不可逆的过程. 就是从无锁--->偏向锁--->轻量级锁--->重量级锁
  2. 锁的粗化
  3. 锁的消除
  4. 自旋锁

二. 线程的逃逸分析

使用逃逸分析,编译器可以对代码做如下优化:

一、同步省略。如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。

二、将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会逃逸,对象可能是栈分配的候选,而不是堆分配。

三、分离对象或标量替换。有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。

是不是所有的对象和数组都会在堆内存分配空间?

不一定

在Java代码运行时,通过JVM参数可指定是否开启逃逸分析, -XX:+DoEscapeAnalysis : 表示开启逃逸分析 -XX:-DoEscapeAnalysis : 表示关闭逃逸分析。从jdk 1.7开始已经默认开启逃逸分析,如需关闭,需要指定-XX:-DoEscapeAnalysis

关于逃逸分析的案例论证见Git课程源码

代码语言:javascript
复制
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;
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、其他锁的概念(这个其他相对于第4节而言)
    • 1. 锁的粗化
      • 2. 锁的消除
        • 3. 从jvm角度出发, 对Synchronized的优化
        • 二. 线程的逃逸分析
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档