sychronized理解
Posted 哈特谢普苏特
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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就会从偏向锁最终升级为重量级锁,造成从用户态切换到内核态。
以上是关于sychronized理解的主要内容,如果未能解决你的问题,请参考以下文章