当前位置: 首页 > 后端技术 > Java

深入JVM底层内置锁synchronized

时间:2023-04-01 19:01:39 Java

前言上一章带你了解了Java对象头的组成。本节带你了解synchronized关键字的底层原理和锁的升级过程。详细解释了synchronized的原理。一种对象锁(锁是对象而不是引用),函数的粒度是对象,可以用来实现对临界资源的同步互斥访问,是可重入的。什么是监视器?在Java虚拟机(HotSpot)中,一个Monitor是由ObjectMonitor实现的。同步对象锁,MarkWord锁标志为10,这里指针指向Monitor对象的起始地址。它的主要数据结构如下ObjectMonitor(){_header=NULL;_count=0;//记录数_waiters=0,_recursions=0;_object=NULL;_owner=NULL;_WaitSet=NULL;//处于等待状态的线程,将被添加到_WaitSet_WaitSetLock=0;_Responsible=NULL;_成功=空;_cxq=空;FreeNext=NULL;_EntryList=NULL;//处于等待锁块状态的线程会被添加到列表中_SpinFreq=0;_自旋时钟=0;所有者线程=0;}ObjectMonitor中有两个队列,_WaitSet和_EntryList,用来保存ObjectWaiter对象的列表(每个等待锁的线程都会封装成一个ObjectWaiter对象),_owner指向ObjectMonitor对象,当多个线程访问一个同时一段同步代码:首先,它们会进入_EntryList集合。当线程获得对象的监视器后,进入_Owner区域,将监视器中的owner变量设置为当前线程。同时,计数器计数加1;如果线程调用wait()方法,当前持有的monitor将被释放,owner变量恢复为null,count减1。同时线程进入WaitSet集合等待被唤醒;如果当前线程执行完毕,也会释放monitor(锁)并重置count的值,以便其他线程进入并获取monitor(锁);synchronized的底层原理是基于JVM内置锁实现的,通过内部对象Monitor(监视器锁),基于进入和退出Monitor对象实现方法与代码块同步,实现监视器锁取决于底层操作系统JVM内置锁的Mutex锁(互斥锁)实现在1.5之后的版本中得到了很大的优化,如LockCoarsening、LockElimination、LightweightLocking、偏向锁(BiasedLocking)、自适应自旋(AdaptiveSpinning)等和其他技术来减少锁操作的开销。每个同步对象都有自己的Monitor(监控锁):同步锁升级过程publicclassTest04{privatestaticObjectobjectLock=newObject();publicstaticvoidmain(String[]args)throwsInterruptedException{//-XX:BiasedLockingStartupDelay=0强制打开//System.out.println(">>----------------无锁定状态001--------------------<<");System.out.println(ClassLayout.parseInstance(objectLock).toPrintable());System.out.println("开启了偏向锁,但是偏向锁没有关联到偏向锁线程");synchronized(objectLock){//偏向锁关联偏向锁线程System.out.println("偏向锁开启,偏向我们主线程");System.out.println(ClassLayout.parseInstance(objectLock).toPrintable());}//取消偏向锁是另一个与偏向锁线程竞争的线程newThread(newRunnable(){@Overridepublicvoidrun(){synchronized(objectLock){try{System.out.println(ClassLayout.parseInstance(objectLock).toPrintable());线程.睡眠(5000);System.out.println("子线程:升级为轻量级锁");}catch(Exceptione){}}}},"子线程1").start();线程.睡眠(1000);同步();}publicstaticvoidsync()throwsInterruptedException{System.out.println("主线程获取锁权重级别锁");//1101000001000000同步(objectLock){System.out.println(ClassLayout.parseInstance(objectLock).toPrintable());}}}总结本文主要介绍synchronized的底层原理