synchronized是解决线程安全的问题,常用在 同步普通方法、静态方法、代码块中
非公平、可重入
每个对象有一个锁和一个等待队列,锁只能被一个线程持有,其他需要锁的线程需要阻塞等待。锁被释放后,对象会从队列中取出一个并唤醒,唤醒哪个线程是不确定的,不保证公平性
两种形式:
方法:生成的字节码文件中会多一个 ACC_SYNCHRONIZED 标志位,当一个线程访问方法时,会去检查是否存在ACC_SYNCHRONIZED标识,如果存在,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象,也叫隐式同步
代码块:加了 synchronized 关键字的代码段,生成的字节码文件会多出 monitorenter 和 monitorexit 两条指令,每个monitor维护着一个记录着拥有次数的计数器, 未被拥有的monitor的该计数器为0,当一个线程获执行monitorenter后,该计数器自增1;当同一个线程执行monitorexit指令的时候,计数器再自减1。当计数器为0的时候,monitor将被释放.也叫显式同步
两种本质上没有区别,底层都是通过monitor来实现同步, 只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成
-
同步方法字节码
-
同步代码块字节码
- jdk1.6后进行了优化,你知道哪些大的变化
有得到锁的资源进入Block状态,涉及到操作系统用户模式和内核模式的切换,代价比较高
jdk6进行了优化,增加了从偏向锁到轻量级锁再到重量级锁的过渡,但是在最终转变为重量级锁之后,性能仍然较低