zoukankan      html  css  js  c++  java
  • 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的优化

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

    二. 线程的逃逸分析

    使用逃逸分析,编译器可以对代码做如下优化:
    一、同步省略。如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。
    二、将堆分配转化为栈分配。如果一个对象在子程序中被分配,要使指向该对象的指针永远不会逃逸,对象可能是栈分配的候选,而不是堆分配。
    三、分离对象或标量替换。有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在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;
        }
    }

    as

  • 相关阅读:
    adb 常用命令及操作
    服务器被黑检查命令
    linux总结
    mysql数据库常用操作
    Python字符串所有操作函数
    Python提示信息表示内容
    Linux基础命令wget(如何联网下载?)
    Linux基础命令sz
    Linux基础命令rz
    Linux基础命令find
  • 原文地址:https://www.cnblogs.com/ITPower/p/13631548.html
Copyright © 2011-2022 走看看