synchronized语法:1、synchronized语句;2、synchronized方法
1、monitorenter和monitorexit字节码;依赖于底层的操作系统的Mutex Lock来实现的
2、会被翻译成普通的方法调用和返回指令如:invokevirtual、areturn指令
原理:用户线程阻塞,内核线程启动,设计到用户线成与内核线程的切换,花销较大
JVM 对于锁的优化
一、偏向锁(Biased Locking)
jdk1.6之后默认开启。参数开启方式:-XX:+UseBiasedLocking,启动默认五秒之后生效。可以立即生效:-XX:BiasedLockingStartupDelay=0
注意:此锁是JVM内部锁,不是应用锁。所以如果优化会对整个应用产生影响,需要慎重。
在竞争激烈的场合没有太强的优化效果,反而有可能降低性能。
原理:1、锁对象中有markword标志位,当前线程、锁的状态
|当前线程|锁的时间戳|年龄|锁的标示位|是否锁定
好处:在竞争不激烈的环境,并且同一个线程多次请求的时候,完全可以采用synchionrized来实现,代码简介,维护方便。其实就是少了同步
例如:70%以上的请求都可能设计不到锁竞争
坏处:在竞争激烈的环境,此锁完全没有开发的其他锁性能高
实例:
public class Baised {
//内部使用了同步锁
public static List<Integer> numberList=new Vector<Integer>();
public static void main(String[] args) {
long begin=System.currentTimeMillis();
int count=0;
int startnum=0;
while (count<10000000) {
numberList.add(startnum);
startnum+=2;
count++;
}
long end=System.currentTimeMillis();
System.out.println("time-->"+(end-begin));
}
}
jvm参数:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 -Xmx512m -Xms512m
需要时间:time-->345
jvm参数:-XX:-UseBiasedLocking -Xmx512m -Xms512m
需要时间:time-->542
二、轻量级锁(Lightweight Locking)
当线程进入轻量锁之后,会赋值markword到自己的线程栈中。利用cas替换赋值,加锁,如果失败进入膨胀锁。
三、锁膨胀
进入膨胀锁,会调用系统mutex进入重量锁,有可能挂起。内核线程切换,花费较大
四、适应性自选锁(Adaptive Spinning)
进入自选之后,在临界区争取一定自选次数。自旋次数1.7之后,jvm自行优化。
五、锁消除(Lock Elimination)
在jit编译时,通过上下文扫描,去掉不可能存在共享资源竞争的锁。因此来提高性能。
例子:
public class LockEliminate {
private static final int CIRCLE = 2000000;
public static void main(String args[]) {
long begin=System.currentTimeMillis();
for(int i=0;i<CIRCLE;i++){
createStringBuffer("JVM", "LockEliminate");
}
long end=System.currentTimeMillis();
System.out.println("time-->"+(end-begin));
}
public static String createStringBuffer(String s1,String s2){
StringBuffer sb=new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
}
JVM 参数:-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks
time-->127
JVM 参数:-server -XX:+DoEscapeAnalysis -XX:-EliminateLocks
time-->269
针对markword参考