大家好,我是你的好朋友思创斯。今天说一说java并发之父doug lea_高并发多线程java,希望您对编程的造诣更进一步.
java实现同步互斥访问有两种方式,synchronized和lock。
sychronized是java实现的内置锁,由jvm实现。通过编译synchronized代码块为字节码可以发现,加锁逻辑被翻译为monitorenter和monitorexit两条指令。synchronized是对象锁,锁的是monitor对象,对于锁的实现这里不再解释,其由jvm实现,实现原理reentrantlock的原理类似,都是获取不到锁,线程会被挂起在一个队列中。
1、编译字节码
javap -verbose xxx
注:xxx为字节码文件,不需要带.class
2、例子
可以看出同步代码快的上下被monitorenter和monitorexit两条指令包裹,分别代表加锁和解锁。
同时,synchronzed的在1.5版本后还有以一个大优化,就是锁的膨胀升级。在早期版本,synchronized会直接加一把重量级锁。等待锁的线程会被挂起,线程的挂起和激活涉及到从用户态和内核态之间的转换,耗时耗力。在新版本中,synchronized提供了三层锁的升级,从无锁–》偏向锁–》轻量级锁–》重量级锁。
1、锁标识
java对象头中有一段mark word区域,在锁膨胀的过程中,这段空间会标识不同的含义。
2、synchronized锁升级过程
当线程a来争夺锁的时候,首先对象升级为偏向锁。线程a通过cas操作尝试将锁对象的mark word的线程id设置为自己。
如果a还没释放锁的时候,线程b来争夺锁。b通过cas尝试获取锁,失败后,b会申请将锁升级为轻量级锁。线程a会找一个程序安全点,暂停线程,将锁升级为轻量级锁。线程a会将mark word的值拷贝到线程栈中,并且将锁对象的mark word修改为指向其线程栈中锁记录的指针。
此时线程b会通过自旋来尝试获取锁,若一定次数没有获取,就会申请将锁升级为重量级锁,同时进入阻塞状态。等线程a释放锁后,再将线程b唤醒,开启一段新的锁争夺。
文章由思创斯整理,转载请注明出处:https://ispacesoft.com/380245.html