一、简单介绍下对synchronized的理解
二、jdk1.6后进行了优化,你知道哪些大的变化
一、简单介绍下对synchronized的理解
synchronized是解决线程安全的问题,常用在 同步普通方法、静态方法、代码块 中 ? 非公平、可重入 ? 每个对象有一个锁和一个等待队列,锁只能被一个线程持有,其他需要锁的线程需要阻塞等待。锁被释放后,对象会从队列中取出一个并唤醒,唤醒哪个线程是不确定的,不保证公平性
synchronized 用来锁方法:
public synchronized void test(){
System.out.println("this wnn demo");
}
?? ?查看字节码:? ?? ?javac Main.java ?? ?javap -v Main.class?
?生成的字节码文件中会多一个 ACC_SYNCHRONIZED 标志位,当一个线程访问方法时,会去检查是否存在ACC_SYNCHRONIZED标识,如果存在,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象,也叫隐式同步
?synchronized锁代码块:
public void test2(){
synchronized(lock){
System.out.println("this wnn demo ");
}
}
?
加了 synchronized 关键字的代码段,生成的字节码文件会多出 monitorenter 和 monitorexit 两条指令,每个monitor维护着一个记录着拥有次数的计数器, 未被拥有的monitor的该计数器为0,当一个线程获执行monitorenter后,该计数器自增1;当同一个线程执行monitorexit指令的时候,计数器再自减1。当计数器为0的时候,monitor将被释放.也叫显式同步
两种本质上没有区别,底层都是通过monitor来实现同步, 只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成?
二、jdk1.6后进行了优化,你知道哪些大的变化
有得到锁的资源进入Block状态,涉及到操作系统用户模式和内核模式的切换,代价比较高 jdk6进行了优化,增加了从偏向锁到轻量级锁再到重量级锁的过渡,但是在最终转变为重量级锁之后,性能仍然较低
JVM中对象在内存中是分成三部分组成:
锁升级其实就是从偏向锁到轻量级锁再到重量级锁升级的过程,这是JDK1.6提供的优化功能,又称锁膨胀。
轻量级锁是相对于重量锁而言的,在JDK1.6之前,synchronized是通过操作系统的互斥量来实现的,这种实现方式需要再用户态和核心态之间做转换,有很大的性能消耗,这种传统实现锁的方式称之为重量锁。
轻量锁通过CAS实现,对比线程和对象Mark Word,如果更新成功则表示当前线程成功拥有此锁,如果失败,虚拟机会检查对象的Mark Word是否指向当前线程的栈帧,如果是,则说明当前线程已经拥有锁了,否则说明此锁已被其他线程占用了。当2个以上线程争抢此锁,轻量级锁就膨胀为重量级锁,这就是锁升级的过程。
|