sychronized理解

1..class和.dex文件

对于Java而言,编译后生成的是.class文件

而对于android而言,.class文件是中间状态,还需要将.class文件通过dex工具变成.dex文件,最终变成.apk文件

如一个类Demo,注意一定不要将它写在xx.com.example下,而是直接写在java文件夹下(即不要导入任何包)

血的教训,千万不要写入任何路径,否则会像我一样折腾半天

 Demo类定义如下,里面写了一个foo()的方法,且被synchronized修饰(可以对比一下有无修饰生成的.dex文件的不同)


public class Demo {
    public synchronized static void foo() {
        int a = 1;
        int b = 2;
        int c = a * b;
    }
}

生成的.class文件在build/intermediates/javac/debug/路径下(获取.class文件的方法 :  make project即可)

public class Demo {
    public Demo() {
    }

    public static synchronized void foo() {
        int a = 1;
        int b = 2;
        int var10000 = a * b;
    }
}

在android的sdk路径中,会有不同版本的build-tools,在windows下默认的android sdk路径是

C:\Users\xxxx\AppData\Local\Android\Sdk

我们可以使用dx.bat工具将android studio 编译生成的,class文件变成,dex文件

 通过下面的命令就可以将Demo.class文件转成Demo.dex文件并将其存储为txt文件

dx --dex --verbose --dump-to=Demo.dex.txt --dump-method=Demo.foo --verbose-dump Demo.class

但是可能不会成功,Demo.class不在dx.bat所在的路径下  或者 dx.bat的路径不在环境变量中

我采取了第二种方式,将dx.bat的路径加入到环境变量中(就是将C:\Users\xxx\AppData\Local\Android\Sdk\build-tools\28.0.3 加入到path中)

然后再运行,可能还是没有出来想要的结果

此时可能就是因为在写Demo文件的时候import了包名,而dx找不到对应的包,所以无法生成,比如下面写的

package com.example.myapplication;

public class MyTest {
    public synchronized static void foo() {
        int a = 1;
        int b = 2;
        int c = a * b;
    }
}

排除各种错误,此时我们生成了.dex文件

Demo.foo:()V:
regs: 0003; ins: 0000; outs: 0000
  0000: code-address
  0000: local-snapshot
  0000: code-address
  0000: code-address
  0000: local-snapshot
  0000: const/4 v0, #int 1 // #1
  0001: local-start v0 "a": int
  0001: const/4 v1, #int 2 // #2
  0002: local-start v1 "b": int
  0002: mul-int v2, v0, v1
  0004: local-start v2 "c": int
  0004: code-address
  0004: code-address
  0004: local-snapshot
          v0 "a": int
          v1 "b": int
          v2 "c": int
  0004: return-void
  0005: code-address
  debug info
    line_start: 4
    parameters_size: 0000
    0000: prologue end
    0000: line 4
    0001: line 5
    0001: +local v0 a int
    0002: line 6
    0002: +local v1 b int
    0004: line 7
    0004: +local v2 c int
    end sequence
  source file: "Demo.java"

我们也可以通过javap -v -c -s -l Demo.class 直接通过Java的方式编译Demo.class文件

javap -v -c -s -l Demo.class

可以看到通过dex工具编译和直接使用javap编译,生成的指令是不同的。

dex去除了冗余信息,但是指令的地址是2-3个字节,指令更加密集,dex是基于寄存器,寻址方便

而java则是单字节,指令更多,java栈需要更多次load与store指令

2.synchronized 

发现有无synchronized的区别在于monitor-enter和monitor-exit

任意对象都可以成为锁 -> Object

sychronized实质上就是通过monitor的方式去进行控制的。

sychronized虽然有很多好处,可以实现线程安全,但是由于它无法在java层拿到当前对象状态,无法判断锁的状态,以及不清楚当前线程是否被锁住。此外,它是不可中断的,如果线程无法拿到锁,就会一直等待,导致资源的浪费,它是一种非公平锁,可重入锁,在monitor-enter和mointor-exit之间的过程不可控,如果多个线程竞争同一把锁,sychronized就会从偏向锁最终升级为重量级锁,造成从用户态切换到内核态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值