🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在Java语言中存在两种内建的synchronized语法:synchronized语句、synchronized方法。 * synchronized语句:当源代码被编译成字节码的时候,会在同步块的入口位置和退出位置分别插入monitorenter和monitorexit字节码指令; * synchronized方法:在Class文件的方法表中将该方法的access\_flags字段中的synchronized标志位置1。这个在specification中没有明确说明; #### monitorenter 每个对象都有一个锁,也就是监视器(monitor)。当monitor被占有时就表示它被锁定。线程执行monitorenter指令时尝试获取对象所对应的monitor的所有权,过程如下: 1. 如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者; 2. 如果线程已经拥有了该monitor,只是重新进入,则进入monitor的进入数加1; 3. 如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。 #### monitorexit 执行monitorexit的线程必须是相应的monitor的所有者; 指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个monitor的所有权; 在 Java 6 之前,Monitor的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级操作;在JDK1.6及其之前的版本中monitorenter和monitorexit字节码依赖于底层的操作系统的Mutex Lock来实现的,但是由于使用Mutex Lock需要将当前线程挂起并从用户态切换到内核态来执行,这种切换的代价是非常昂贵的。然而在现实中的大部分情况下,同步方法是运行在单线程环境(无锁竞争环境)。如果每次都调用Mutex Lock将严重的影响程序的性能。因此在JDK 1.6之后的版本中对锁的实现做了大量的优化,这些优化在很大程度上减少或避免了Mutex Lock的使用