synchronized 可重入机制
一、一句话核心
同一个线程可以多次获取同一把锁,不会死锁。
- 原理:锁自带计数器,加锁+1,释放-1,归0才真正释放
- 类比:一把家门钥匙能开家里所有房间门
二、为什么必须有可重入?
没有可重入,下面代码会直接死锁:
java
public synchronized void a() { b(); } // 拿了锁调用b()
public synchronized void b() {} // 再拿同一把锁,自己等自己
三、三种锁的可重入实现对比
| 锁状态 | 计数器在哪 | 怎么判断是同一个线程 |
|---|---|---|
| 偏向锁 | 对象头Mark Word | 检查里面存的线程ID |
| 轻量级锁 | 线程栈的Lock Record链表 | 检查锁记录的所有者 |
| 重量级锁 | Monitor对象的count字段 |
检查Monitor的owner |
四、重量级锁(最常考)实现
Monitor核心结构
#mermaid-svg-yATmT3CQWVrdXhC0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yATmT3CQWVrdXhC0 .error-icon{fill:#552222;}#mermaid-svg-yATmT3CQWVrdXhC0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yATmT3CQWVrdXhC0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yATmT3CQWVrdXhC0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yATmT3CQWVrdXhC0 .marker.cross{stroke:#333333;}#mermaid-svg-yATmT3CQWVrdXhC0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yATmT3CQWVrdXhC0 p{margin:0;}#mermaid-svg-yATmT3CQWVrdXhC0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 .cluster-label text{fill:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 .cluster-label span{color:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 .cluster-label span p{background-color:transparent;}#mermaid-svg-yATmT3CQWVrdXhC0 .label text,#mermaid-svg-yATmT3CQWVrdXhC0 span{fill:#333;color:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 .node rect,#mermaid-svg-yATmT3CQWVrdXhC0 .node circle,#mermaid-svg-yATmT3CQWVrdXhC0 .node ellipse,#mermaid-svg-yATmT3CQWVrdXhC0 .node polygon,#mermaid-svg-yATmT3CQWVrdXhC0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yATmT3CQWVrdXhC0 .rough-node .label text,#mermaid-svg-yATmT3CQWVrdXhC0 .node .label text,#mermaid-svg-yATmT3CQWVrdXhC0 .image-shape .label,#mermaid-svg-yATmT3CQWVrdXhC0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-yATmT3CQWVrdXhC0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yATmT3CQWVrdXhC0 .rough-node .label,#mermaid-svg-yATmT3CQWVrdXhC0 .node .label,#mermaid-svg-yATmT3CQWVrdXhC0 .image-shape .label,#mermaid-svg-yATmT3CQWVrdXhC0 .icon-shape .label{text-align:center;}#mermaid-svg-yATmT3CQWVrdXhC0 .node.clickable{cursor:pointer;}#mermaid-svg-yATmT3CQWVrdXhC0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yATmT3CQWVrdXhC0 .arrowheadPath{fill:#333333;}#mermaid-svg-yATmT3CQWVrdXhC0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yATmT3CQWVrdXhC0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yATmT3CQWVrdXhC0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yATmT3CQWVrdXhC0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yATmT3CQWVrdXhC0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yATmT3CQWVrdXhC0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yATmT3CQWVrdXhC0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yATmT3CQWVrdXhC0 .cluster text{fill:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 .cluster span{color:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yATmT3CQWVrdXhC0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yATmT3CQWVrdXhC0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-yATmT3CQWVrdXhC0 .icon-shape,#mermaid-svg-yATmT3CQWVrdXhC0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yATmT3CQWVrdXhC0 .icon-shape p,#mermaid-svg-yATmT3CQWVrdXhC0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yATmT3CQWVrdXhC0 .icon-shape .label rect,#mermaid-svg-yATmT3CQWVrdXhC0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yATmT3CQWVrdXhC0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yATmT3CQWVrdXhC0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yATmT3CQWVrdXhC0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Monitor
owner: 谁拿着锁
count: 重入次数
执行流程
#mermaid-svg-mIT6OWpTDkETMVtV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mIT6OWpTDkETMVtV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mIT6OWpTDkETMVtV .error-icon{fill:#552222;}#mermaid-svg-mIT6OWpTDkETMVtV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mIT6OWpTDkETMVtV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mIT6OWpTDkETMVtV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mIT6OWpTDkETMVtV .marker.cross{stroke:#333333;}#mermaid-svg-mIT6OWpTDkETMVtV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mIT6OWpTDkETMVtV p{margin:0;}#mermaid-svg-mIT6OWpTDkETMVtV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mIT6OWpTDkETMVtV .cluster-label text{fill:#333;}#mermaid-svg-mIT6OWpTDkETMVtV .cluster-label span{color:#333;}#mermaid-svg-mIT6OWpTDkETMVtV .cluster-label span p{background-color:transparent;}#mermaid-svg-mIT6OWpTDkETMVtV .label text,#mermaid-svg-mIT6OWpTDkETMVtV span{fill:#333;color:#333;}#mermaid-svg-mIT6OWpTDkETMVtV .node rect,#mermaid-svg-mIT6OWpTDkETMVtV .node circle,#mermaid-svg-mIT6OWpTDkETMVtV .node ellipse,#mermaid-svg-mIT6OWpTDkETMVtV .node polygon,#mermaid-svg-mIT6OWpTDkETMVtV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mIT6OWpTDkETMVtV .rough-node .label text,#mermaid-svg-mIT6OWpTDkETMVtV .node .label text,#mermaid-svg-mIT6OWpTDkETMVtV .image-shape .label,#mermaid-svg-mIT6OWpTDkETMVtV .icon-shape .label{text-anchor:middle;}#mermaid-svg-mIT6OWpTDkETMVtV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mIT6OWpTDkETMVtV .rough-node .label,#mermaid-svg-mIT6OWpTDkETMVtV .node .label,#mermaid-svg-mIT6OWpTDkETMVtV .image-shape .label,#mermaid-svg-mIT6OWpTDkETMVtV .icon-shape .label{text-align:center;}#mermaid-svg-mIT6OWpTDkETMVtV .node.clickable{cursor:pointer;}#mermaid-svg-mIT6OWpTDkETMVtV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mIT6OWpTDkETMVtV .arrowheadPath{fill:#333333;}#mermaid-svg-mIT6OWpTDkETMVtV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mIT6OWpTDkETMVtV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mIT6OWpTDkETMVtV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mIT6OWpTDkETMVtV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mIT6OWpTDkETMVtV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mIT6OWpTDkETMVtV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mIT6OWpTDkETMVtV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mIT6OWpTDkETMVtV .cluster text{fill:#333;}#mermaid-svg-mIT6OWpTDkETMVtV .cluster span{color:#333;}#mermaid-svg-mIT6OWpTDkETMVtV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mIT6OWpTDkETMVtV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mIT6OWpTDkETMVtV rect.text{fill:none;stroke-width:0;}#mermaid-svg-mIT6OWpTDkETMVtV .icon-shape,#mermaid-svg-mIT6OWpTDkETMVtV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mIT6OWpTDkETMVtV .icon-shape p,#mermaid-svg-mIT6OWpTDkETMVtV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mIT6OWpTDkETMVtV .icon-shape .label rect,#mermaid-svg-mIT6OWpTDkETMVtV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mIT6OWpTDkETMVtV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mIT6OWpTDkETMVtV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mIT6OWpTDkETMVtV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
线程拿锁
owner是自己?
count+1
owner是空?
owner=自己, count=1
排队等
执行代码
释放: count-1
count=0?
owner清空, 唤醒排队线程
锁还在自己手里
五、轻量级锁实现
用栈里多个锁记录代替计数器:
#mermaid-svg-vzizJt8FbeAbiz3q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vzizJt8FbeAbiz3q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vzizJt8FbeAbiz3q .error-icon{fill:#552222;}#mermaid-svg-vzizJt8FbeAbiz3q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vzizJt8FbeAbiz3q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vzizJt8FbeAbiz3q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vzizJt8FbeAbiz3q .marker.cross{stroke:#333333;}#mermaid-svg-vzizJt8FbeAbiz3q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vzizJt8FbeAbiz3q p{margin:0;}#mermaid-svg-vzizJt8FbeAbiz3q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vzizJt8FbeAbiz3q .cluster-label text{fill:#333;}#mermaid-svg-vzizJt8FbeAbiz3q .cluster-label span{color:#333;}#mermaid-svg-vzizJt8FbeAbiz3q .cluster-label span p{background-color:transparent;}#mermaid-svg-vzizJt8FbeAbiz3q .label text,#mermaid-svg-vzizJt8FbeAbiz3q span{fill:#333;color:#333;}#mermaid-svg-vzizJt8FbeAbiz3q .node rect,#mermaid-svg-vzizJt8FbeAbiz3q .node circle,#mermaid-svg-vzizJt8FbeAbiz3q .node ellipse,#mermaid-svg-vzizJt8FbeAbiz3q .node polygon,#mermaid-svg-vzizJt8FbeAbiz3q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vzizJt8FbeAbiz3q .rough-node .label text,#mermaid-svg-vzizJt8FbeAbiz3q .node .label text,#mermaid-svg-vzizJt8FbeAbiz3q .image-shape .label,#mermaid-svg-vzizJt8FbeAbiz3q .icon-shape .label{text-anchor:middle;}#mermaid-svg-vzizJt8FbeAbiz3q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vzizJt8FbeAbiz3q .rough-node .label,#mermaid-svg-vzizJt8FbeAbiz3q .node .label,#mermaid-svg-vzizJt8FbeAbiz3q .image-shape .label,#mermaid-svg-vzizJt8FbeAbiz3q .icon-shape .label{text-align:center;}#mermaid-svg-vzizJt8FbeAbiz3q .node.clickable{cursor:pointer;}#mermaid-svg-vzizJt8FbeAbiz3q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vzizJt8FbeAbiz3q .arrowheadPath{fill:#333333;}#mermaid-svg-vzizJt8FbeAbiz3q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vzizJt8FbeAbiz3q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vzizJt8FbeAbiz3q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vzizJt8FbeAbiz3q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vzizJt8FbeAbiz3q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vzizJt8FbeAbiz3q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vzizJt8FbeAbiz3q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vzizJt8FbeAbiz3q .cluster text{fill:#333;}#mermaid-svg-vzizJt8FbeAbiz3q .cluster span{color:#333;}#mermaid-svg-vzizJt8FbeAbiz3q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vzizJt8FbeAbiz3q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vzizJt8FbeAbiz3q rect.text{fill:none;stroke-width:0;}#mermaid-svg-vzizJt8FbeAbiz3q .icon-shape,#mermaid-svg-vzizJt8FbeAbiz3q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vzizJt8FbeAbiz3q .icon-shape p,#mermaid-svg-vzizJt8FbeAbiz3q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vzizJt8FbeAbiz3q .icon-shape .label rect,#mermaid-svg-vzizJt8FbeAbiz3q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vzizJt8FbeAbiz3q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vzizJt8FbeAbiz3q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vzizJt8FbeAbiz3q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线程栈
锁记录3
锁记录2
锁记录1 ← 对象头指向这里
- 重入1次,栈里多1个锁记录
- 释放1次,栈里弹出1个锁记录
- 全弹完,锁真正释放
六、常见误区
| 误区 | 正确结论 |
|---|---|
| 不同线程也能重入 | 只允许同一个线程 |
| 静态和普通方法能互相重入 | 锁的对象不同,不能 |
| 重入次数无限 | 最多2^31-1次,超了报错 |
七、关键总结
| 特性 | 说明 |
|---|---|
| 核心目的 | 避免自己把自己卡死 |
| 性能影响 | 几乎为0,只是计数器加减 |
| 释放规则 | 加锁多少次,必须释放多少次 |