<section data-role="outer" label="Powered by 135editor.com" style="font-size: 16px;" data-mpa-powered-by="yiban.io"><p style="text-align: right;"><span style="font-family: 微软雅黑, "Microsoft YaHei"caret-color: rgb(255, 0, 0);font-size: 10px;color: rgb(178, 178, 178);">来源:jianshu.com/p/e674ee68fd3f</span></p><h1 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">1、为什么要用锁?</span></h1><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">锁-是为了解决并发操作引起的脏读、数据不一致的问题。</span></p><p><br></p><h1 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2、锁实现的基本原理</span></h1><p><br></p><h2 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.1、volatile</span></h2><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="262" data-ratio="0.4588235294117647" data-type="png" data-w="765" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn0KE1Bu0k2NSRU6nCd4hA6CIibxHz1IkgiaQWc9Hff2QP3M2nt1OjOzjg/640?wx_fmt=png" _width="677px" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133233180-190053147.png" style="width: 677px !important; height: auto !important; visibility: visible !important;" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">结论:如果volatile变量修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。</span></p><p><br></p><h2 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.2、synchronized</span></h2><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">synchronized通过锁机制实现同步。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">先来看下利用synchronized实现同步的基础:Java中的每一个对象都可以作为锁。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">具体表现为以下3种形式。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">对于普通同步方法,锁是当前实例对象。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">对于静态同步方法,锁是当前类的Class对象。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">对于同步方法块,锁是Synchonized括号里配置的对象。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。</span></p><p><br></p><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.2.1 synchronized实现原理</span></h3><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">synchronized是基于Monitor来实现同步的。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">Monitor从两个方面来支持线程之间的同步:</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">互斥执行</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">协作</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">1、Java 使用</span><span style="font-size: 15px;caret-color: red;font-family: 微软雅黑, 'Microsoft YaHei';">对象锁 ( 使用 synchronized 获得对象锁 ) 保证工作在共享的数据集上的线程互斥执行。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2、使用 notify/notifyAll/wait 方法来协同不同线程之间的工作。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">3、Class和Object都关联了一个Monitor。</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="499" data-cropsely1="0" data-cropsely2="318" data-ratio="0.638" data-type="png" data-w="500" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn8A7zT9dIqTJ6wsa8ekVdd1NdIbqhoX2NCictftP489Z7ZToMicxPyVtA/640?wx_fmt=png" data-backw="500" data-backh="319" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn8A7zT9dIqTJ6wsa8ekVdd1NdIbqhoX2NCictftP489Z7ZToMicxPyVtA/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133253812-2128863132.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">Monitor 的工作机理</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">线程进入同步方法中。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">为了继续执行临界区代码,线程必须获取 Monitor 锁。如果获取锁成功,将成为该监视者对象的拥有者。任一时刻内,监视者对象只属于一个活动线程(The Owner)</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">拥有监视者对象的线程可以调用 wait() 进入等待集合(Wait Set),同时释放监视锁,进入等待状态。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">其他线程调用 notify() / notifyAll() 接口唤醒等待集合中的线程,这些等待的线程需要重新获取监视锁后才能执行 wait() 之后的代码。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">同步方法执行完毕了,线程退出临界区,并释放监视锁。</span></p><p><br></p><p>参考文档:<span style="color: #A5A5A5;font-size: 15px;">https://www.ibm.com/developerworks/cn/java/j-lo-synchronized</span></p><p><br></p><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.2.2 synchronized具体实现</span></h3><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">1、同步代码块采用monitorenter、monitorexit指令显式的实现。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2、同步方法则使用ACC_SYNCHRONIZED标记符隐式的实现。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">通过实例来看看具体实现:</span></p><p><br></p><pre style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;letter-spacing: 0.544px;color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);font-family: Consolas, Menlo, Courier, monospace;box-sizing: border-box !important;word-wrap: break-word !important;"><code class="hljs java" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);padding: 0.5em;font-size: 11px;max-width: 100%;display: block;overflow-x: auto;line-height: 15px;word-spacing: -3px;letter-spacing: 0px;background: rgb(29, 31, 33);color: rgb(197, 200, 198);font-family: Consolas, Inconsolata, Courier, monospace;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: normal !important;word-break: normal !important;overflow-y: auto !important;"><span class="" style="max-width: 100%;color: rgb(178, 148, 187);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword"><span class="hljs-keyword">public</span></span></span> <span class="" style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="" style="max-width: 100%;color: rgb(178, 148, 187);word-break: inherit !important;"><span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span></span></span><span class="hljs-class"><span class="hljs-class"> </span></span><span class="" style="max-width: 100%;color: rgb(129, 162, 190);word-break: inherit !important;"><span class="hljs-class"><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">SynchronizedTest</span></span></span></span></span><span class="hljs-class"><span class="hljs-class"> </span></span></span>{<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> <span class="" style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="" style="max-width: 100%;color: rgb(178, 148, 187);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"> </span></span><span class="" style="max-width: 100%;color: rgb(178, 148, 187);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">synchronized</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"> </span></span><span class="" style="max-width: 100%;color: rgb(178, 148, 187);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"> </span></span><span class="" style="max-width: 100%;color: rgb(129, 162, 190);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">method1</span></span></span></span></span><span class="" style="max-width: 100%;color: rgb(222, 147, 95);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span></span></span></span>{<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> System.out.println(<span class="" style="max-width: 100%;color: rgb(181, 189, 104);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-string"><span class="hljs-string">"Hello World!"</span></span></span>);<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> }<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> <span class="" style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="" style="max-width: 100%;color: rgb(178, 148, 187);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"> </span></span><span class="" style="max-width: 100%;color: rgb(178, 148, 187);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span></span></span><span class="hljs-function"><span class="hljs-function"> </span></span><span class="" style="max-width: 100%;color: rgb(129, 162, 190);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">method2</span></span></span></span></span><span class="" style="max-width: 100%;color: rgb(222, 147, 95);word-break: inherit !important;"><span class="hljs-function"><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span></span></span></span>{<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> <span class="" style="max-width: 100%;color: rgb(178, 148, 187);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword"><span class="hljs-keyword">synchronized</span></span></span> (<span class="" style="max-width: 100%;color: rgb(178, 148, 187);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-keyword"><span class="hljs-keyword">this</span></span></span>){<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> System.out.println(<span class="" style="max-width: 100%;color: rgb(181, 189, 104);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span class="hljs-string"><span class="hljs-string">"Hello World!"</span></span></span>);<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> }<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"> }<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;">}<br style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: inherit !important;word-break: inherit !important;"></code></pre><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">javap编译后的字节码如下:</span></p><p><br></p><figure style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);max-width: 100%;letter-spacing: 0.544px;color: rgb(52, 73, 94);background-color: rgb(255, 255, 255);font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="784" data-ratio="1.3741666666666668" data-type="png" data-w="1200" title="" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnGKbI0kcSdRiaTVEIeDIHzQia2LuIOHcIknEmCpdHTADKh0m7XEWmFRqg/640?wx_fmt=png" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); margin-right: auto; margin-left: auto; border-style: solid; border-width: 2px; border-color: rgb(238, 238, 238); border-radius: 6px; display: block; box-sizing: border-box !important; overflow-wrap: break-word !important; visibility: visible !important; width: 100% !important; height: auto !important;" data-backw="570.025" data-backh="783.025" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnGKbI0kcSdRiaTVEIeDIHzQia2LuIOHcIknEmCpdHTADKh0m7XEWmFRqg/640?wx_fmt=png" _width="100%" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133315873-1830567477.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">monitorenter</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">每一个对象都有一个monitor,一个monitor只能被一个线程拥有。当一个线程执行到monitorenter指令时会尝试获取相应对象的</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">monitor,获取规则如下:</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">如果monitor的进入数为0,则该线程可以进入monitor,并将monitor进入数设置为1,该线程即为monitor的拥有者。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">如果当前线程已经拥有该monitor,只是重新进入,则进入monitor的进入数加1,所以synchronized关键字实现的锁是可重入的锁。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">如果monitor已被其他线程拥有,则当前线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">monitorexit</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">只有拥有相应对象的monitor的线程才能执行monitorexit指令。每执行一次该指令monitor进入数减1,当进入数为0时当前线程释放monitor,此时其他阻塞的线程将可以尝试获取该monitor。</span></p><p><br></p><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.2.3 锁存放的位置</span></h3><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">锁标记存放在Java对象头的Mark Word中。</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="99" data-ratio="0.175" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn0Y5RS19A7pTVD6ibG6vxIdkxARsDDoV71XRrlrLnRhwD2kV4bYgfnRQ/640?wx_fmt=png" data-backw="574" data-backh="101" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn0Y5RS19A7pTVD6ibG6vxIdkxARsDDoV71XRrlrLnRhwD2kV4bYgfnRQ/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133405678-40897258.png" crossorigin="anonymous" data-fail="0"><figcaption><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">Java对象头长度</span></figcaption></figure><figure><img data-backh="62" data-backw="574" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz/QCu849YTaIPksEhmXNlhegkc6ice6GYEnBA28fkQTqCR1Ju9yldmCcgNCPJ1NX0QaYFKINM78RMiats7rTwFX3Gg/640?wx_fmt=other" data-oversubscription-url="http://mmbiz.qpic.cn/mmbiz_jpg/SUicwdN39QsPJmMqSzaTSOHe08McwPRo00ibW8dXuicECprdI9fJvHkibnlto2h8EbAicAjATALJqy2GAlFYxeHl0UA/0?wx_fmt=jpeg" data-ratio="0.11" data-src="https://mmbiz.qpic.cn/mmbiz_jpg/SUicwdN39QsPJmMqSzaTSOHe08McwPRo00ibW8dXuicECprdI9fJvHkibnlto2h8EbAicAjATALJqy2GAlFYxeHl0UA/640?wx_fmt=jpeg" data-type="jpeg" data-w="1200" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133432358-1895366965.png" crossorigin="anonymous" data-fail="0"><figcaption><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">32位JVM Mark Word 结构</span></figcaption></figure><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="132" data-ratio="0.23166666666666666" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnVrmfqajSfia99uJFVViaq3iax3cC3a6HLOgu4IBI5MmOHEIbeYhbiaOfTw/640?wx_fmt=png" data-backw="574" data-backh="133" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnVrmfqajSfia99uJFVViaq3iax3cC3a6HLOgu4IBI5MmOHEIbeYhbiaOfTw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133453495-1950846084.png" crossorigin="anonymous" data-fail="0"><figcaption><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">32位JVM Mark Word 状态变化</span></figcaption></figure><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="96" data-ratio="0.16916666666666666" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEno7R9LPLGo3OSmiaLZI43120UwcUN6iaiaXwXpjBceZHC8wiaGoXSDpxgsQ/640?wx_fmt=png" data-backw="574" data-backh="97" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEno7R9LPLGo3OSmiaLZI43120UwcUN6iaiaXwXpjBceZHC8wiaGoXSDpxgsQ/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src=https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133510746-1611249084.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">64位JVM Mark Word 结构</span></p><p><br></p><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.2.3 synchronized的锁优化</span></h3><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">JavaSE1.6为了减少获得锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">在JavaSE1.6中,锁一共有4种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。</span></p><p><br></p><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">偏向锁:</span></h4><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">无锁竞争的情况下为了减少锁竞争的资源开销,引入偏向锁。</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="556" data-ratio="0.975" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEneNic6BzhLGIN2p4uPHwrP9cBHbg8AaSgyqJCDBgJxMMeUlMAkcfOlvw/640?wx_fmt=png" data-backw="574" data-backh="559" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEneNic6BzhLGIN2p4uPHwrP9cBHbg8AaSgyqJCDBgJxMMeUlMAkcfOlvw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133529252-1066047276.png" crossorigin="anonymous" data-fail="0"></figure><h4 style="font-weight: bold;line-height: 1.6;"></h4><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></h4><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">轻量级锁:</span></h4><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">轻量级锁所适应的场景是线程交替执行同步块的情况</span><span style="font-size: 15px;caret-color: red;font-family: 微软雅黑, 'Microsoft YaHei';">。</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="556" data-ratio="0.975" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEneNic6BzhLGIN2p4uPHwrP9cBHbg8AaSgyqJCDBgJxMMeUlMAkcfOlvw/640?wx_fmt=png" data-backw="574" data-backh="559" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEneNic6BzhLGIN2p4uPHwrP9cBHbg8AaSgyqJCDBgJxMMeUlMAkcfOlvw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133551972-160806677.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">锁粗化(Lock Coarsening):也就是减少不必要的紧连在一起的unlock,lock操作,将多个连续的锁扩展成一个范围更大的锁。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">锁消除(Lock Elimination):锁削除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行削除。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">适应性自旋(Adaptive Spinning):自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而它将允许自旋等待持续相对更长的时间,比如100个循环。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">另一方面,如果对于某个锁,自旋很少成功获得过,那在以后要获取这个锁时将可能省略掉自旋过程,以避免浪费处理器资源。</span></p><p><br></p><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.2.4 锁的优缺点对比</span></h3><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="146" data-ratio="0.25583333333333336" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnUaFbGdC0zfEbiaicq6bWK4FZJ6RqVJOCtjica8exVZB4KZLmd1s7BcnAQ/640?wx_fmt=png" data-backw="574" data-backh="146" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnUaFbGdC0zfEbiaicq6bWK4FZJ6RqVJOCtjica8exVZB4KZLmd1s7BcnAQ/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133615526-2001355017.png" crossorigin="anonymous" data-fail="0"></figure><h2 style="font-weight: bold;line-height: 1.6;"></h2><h2 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></h2><h2 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2.3、CAS</span></h2><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">CAS,在Java并发应用中通常指CompareAndSwap或CompareAndSet,即比较并交换。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">1、CAS是一个原子操作,它比较一个内存位置的值并且只有相等时修改这个内存位置的值为新的值,保证了新的值总是基于最新的信息计算的,如果有其他线程在这期间修改了这个值则CAS失败。CAS返回是否成功或者内存位置原来的值用于判断是否CAS成功。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">2、JVM中的CAS操作是利用了处理器提供的CMPXCHG指令实现的。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">优点:</span></p><p><br></p><ul class="list-paddingleft-2" style="list-style-type: none;"><li><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">竞争不大的时候系统开销小。</span></p></li><li><p><br></p></li></ul><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">缺点:</span></p><p><br></p><ul class="list-paddingleft-2" style="list-style-type: none;"><li><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">循环时间长开销大。</span></p></li><li><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">ABA问题。</span></p></li><li><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">只能保证一个共享变量的原子操作。</span></p></li><li><p><br></p></li></ul><h1 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">3、Java中的锁实现</span></h1><p><br></p><h2 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">3.1、队列同步器(AQS)</span></h2><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架。</span></p><p><br></p><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">3.1.1、它使用了一个int成员变量表示同步状态。</span></h3><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="152" data-ratio="0.26666666666666666" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn8XHoomr2cquAaEUFe2z5icicIRbJibPyYN36JLoYQTsW4SHsdo7DLPxEw/640?wx_fmt=png" data-backw="574" data-backh="154" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn8XHoomr2cquAaEUFe2z5icicIRbJibPyYN36JLoYQTsW4SHsdo7DLPxEw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133632853-1001996493.png" crossorigin="anonymous" data-fail="0"></figure><h3 style="font-weight: bold;line-height: 1.6;"></h3><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></h3><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">3.1.2、通过内置的FIFO双向队列来完成获取锁线程的排队工作。</span></h3><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">同步器包含两个节点类型的应用,一个指向头节点,一个指向尾节点,未获取到锁的线程会创建节点线程安全(compareAndSetTail)的加入队列尾部。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">同步队列遵循FIFO,首节点是获取同步状态成功的节点。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></p><ul class="list-paddingleft-2" style="list-style-type: none;"><li><figure><img data-cropselx1="0" data-cropselx2="533" data-cropsely1="0" data-cropsely2="173" data-ratio="0.325" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnXAnZMvGKdXibQGBtM3S8EboqtiaqZLjicZgrGdYvBCdKGib6SVjjV5m3Gw/640?wx_fmt=png" data-backw="539" data-backh="175" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnXAnZMvGKdXibQGBtM3S8EboqtiaqZLjicZgrGdYvBCdKGib6SVjjV5m3Gw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133648791-1050811559.png" crossorigin="anonymous" data-fail="0"></figure></li></ul><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">未获取到锁的线程将创建一个节点,设置到尾节点。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">如下图所示:</span></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="208" data-ratio="0.365" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnFiahtwJRMYh0Hp4Y8Lia79AMcUmGbJInKnIicIMuiaCpkjAFLgsJ1YpI8g/640?wx_fmt=png" data-backw="574" data-backh="210" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnFiahtwJRMYh0Hp4Y8Lia79AMcUmGbJInKnIicIMuiaCpkjAFLgsJ1YpI8g/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133719973-431134712.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">首节点的线程在释放锁时,将会唤醒后继节点。而后继节点将会在获取锁成功时将自己设置为首节点。</span></p><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">如下图所示:</span></p><figure><img data-cropselx1="2" data-cropselx2="531" data-cropsely1="0" data-cropsely2="193" data-ratio="0.27666666666666667" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnUN3do5UjazdvBic02SQsmkGub6eMBMR8ssYcBaUfXjJ0tV1ribPj68LQ/640?wx_fmt=png" data-backw="574" data-backh="158" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnUN3do5UjazdvBic02SQsmkGub6eMBMR8ssYcBaUfXjJ0tV1ribPj68LQ/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133736561-138963095.png" crossorigin="anonymous" data-fail="0"></figure><h3 style="font-weight: bold;line-height: 1.6;"></h3><h3 style="font-weight: bold;line-height: 1.6;"><br></h3><h3 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">3.1.3、独占式/共享式锁获取</span></h3><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">独占式:有且只有一个线程能获取到锁,如:ReentrantLock。</span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">共享式:可以多个线程同时获取到锁,如:CountDownLatch</span></p><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></h4><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">独占式</span></h4><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">每个节点自旋观察自己的前一节点是不是Header节点,如果是,就去尝试获取锁。</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="533" data-cropsely1="0" data-cropsely2="135" data-ratio="0.255" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnMNHticMMzBsDdSDGbp2s4N7yckcQ4x6Qq2rTJRQlh1q6UL9vncZQj6w/640?wx_fmt=png" data-backw="574" data-backh="146" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnMNHticMMzBsDdSDGbp2s4N7yckcQ4x6Qq2rTJRQlh1q6UL9vncZQj6w/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133754059-1054383585.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">独占式锁获取流程:</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="564" data-ratio="0.9883333333333333" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnETznz47tvRbtec3AoduyNcxASp8DMzerR794icPNkjPSYepeZn2jRkw/640?wx_fmt=png" data-backw="574" data-backh="568" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnETznz47tvRbtec3AoduyNcxASp8DMzerR794icPNkjPSYepeZn2jRkw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133809834-20395484.png" crossorigin="anonymous" data-fail="0"></figure><h4 style="font-weight: bold;line-height: 1.6;"></h4><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></h4><h4 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">共享式:</span></h4><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">共享式与独占式的区别:</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="533" data-cropsely1="0" data-cropsely2="300" data-ratio="0.565" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn1qeTXibFkuxicOcHibkJRowMQTRa8JKX9YQDNvQcbiaDB0hGYq7AFhT0YQ/640?wx_fmt=png" data-backw="574" data-backh="324" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn1qeTXibFkuxicOcHibkJRowMQTRa8JKX9YQDNvQcbiaDB0hGYq7AFhT0YQ/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133833324-2045100329.png" crossorigin="anonymous" data-fail="0"></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">共享锁获取流程:</span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="403" data-ratio="0.7061923583662714" data-type="png" data-w="759" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnNMyJGl6b1w1Obwqfl9kPwrgluJ8CTafxURicNXFGf9JLu7iaNHpZ3ruQ/640?wx_fmt=png" data-backw="574" data-backh="406" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnNMyJGl6b1w1Obwqfl9kPwrgluJ8CTafxURicNXFGf9JLu7iaNHpZ3ruQ/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133847909-32641824.png" crossorigin="anonymous" data-fail="0"></figure><h1 style="font-weight: bold;line-height: 1.6;"></h1><h1 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></h1><h1 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">4</span>、锁的使用用例</h1><p><br></p><h2 style="font-weight: bold;line-height: 1.6;"><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">4.1、ConcurrentHashMap的实现原理及使用</span></h2><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></p><p><br></p><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="466" data-ratio="0.8166666666666667" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnzHK1Qt9ibEicX0HXspWBKz5TxPqia8SFusYBdwZJTA4N04n45ngRtqQgw/640?wx_fmt=png" data-backw="574" data-backh="469" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEnzHK1Qt9ibEicX0HXspWBKz5TxPqia8SFusYBdwZJTA4N04n45ngRtqQgw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133903649-1059587046.png" crossorigin="anonymous" data-fail="0"><figcaption><br></figcaption><figcaption><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">ConcurrentHashMap类图</span></figcaption><figcaption><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';"><br></span></figcaption></figure><figure><img data-cropselx1="0" data-cropselx2="570" data-cropsely1="0" data-cropsely2="292" data-ratio="0.5108333333333334" data-type="png" data-w="1200" data-src="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn8WYuoicLufp6B4Hu71YCdvtJRIKXfGI6T9bfAda4z7rRiauP5kR3ILXw/640?wx_fmt=png" data-backw="574" data-backh="293" data-before-oversubscription-url="https://mmbiz.qpic.cn/mmbiz_png/QCu849YTaIPksEhmXNlhegkc6ice6GYEn8WYuoicLufp6B4Hu71YCdvtJRIKXfGI6T9bfAda4z7rRiauP5kR3ILXw/640?wx_fmt=png" style="width: 100% !important; height: auto !important; visibility: visible !important;" _width="100%" class="" src="https://img2018.cnblogs.com/blog/1112483/201911/1112483-20191112133919142-1191235800.png" crossorigin="anonymous" data-fail="0"><figcaption><br></figcaption><figcaption><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">ConcurrentHashMap数据结构</span></figcaption></figure><p><br></p><p><span style="font-size: 15px;font-family: 微软雅黑, 'Microsoft YaHei';">结论:ConcurrentHashMap使用的锁分段技术。首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。</span></p></section>
原文地址:https://mp.weixin.qq.com/s/3BITJAlZUa2AoVFtcV7xsA </div>