forked from itwanger/toBeBetterJavaer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlock.html
More file actions
174 lines (161 loc) · 77.2 KB
/
Copy pathlock.html
File metadata and controls
174 lines (161 loc) · 77.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="generator" content="VuePress 2.0.0-beta.46" />
<meta name="theme" content="VuePress Theme Hope" />
<meta property="og:url" content="https://tobebetterjavaer.com/thread/lock.html"><meta property="og:site_name" content="Java 程序员进阶之路"><meta property="og:title" content="大致了解下Java的锁接口和锁"><meta property="og:type" content="article"><meta property="og:updated_time" content="2022-03-27T08:36:50.000Z"><meta property="og:locale" content="zh-CN"><meta property="article:tag" content="Java"><meta property="article:modified_time" content="2022-03-27T08:36:50.000Z"><script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?5230ac143650bf5eb3c14f3fb9b1d3ec";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script><link rel="stylesheet" href="//at.alicdn.com/t/font_3180624_7cy10l7jqqh.css"><link rel="icon" href="/favicon.ico"><link rel="icon" href="/assets/icon/chrome-mask-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-mask-192.png" type="image/png" sizes="192x192"><link rel="icon" href="/assets/icon/chrome-512.png" type="image/png" sizes="512x512"><link rel="icon" href="/assets/icon/chrome-192.png" type="image/png" sizes="192x192"><link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials"><meta name="theme-color" content="#46bd87"><link rel="apple-touch-icon" href="/assets/icon/apple-icon-152.png"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="msapplication-TileImage" content="/assets/icon/ms-icon-144.png"><meta name="msapplication-TileColor" content="#ffffff"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"><title>大致了解下Java的锁接口和锁 | Java 程序员进阶之路</title><meta name="description" content="一份通俗易懂、风趣幽默的Java学习指南,内容涵盖Java基础、Java并发编程、Java虚拟机、Java企业级开发、Java面试等核心知识点。学Java,就认准Java程序员进阶之路">
<style>
:root {
--bg-color: #fff;
}
html[data-theme="dark"] {
--bg-color: #1d2025;
}
html,
body {
background-color: var(--bg-color);
}
</style>
<script>
const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
const systemDarkMode =
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches;
if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
document.querySelector("html").setAttribute("data-theme", "dark");
}
</script>
<link rel="stylesheet" href="/assets/style.c081fa20.css">
<link rel="modulepreload" href="/assets/app.41bad062.js"><link rel="modulepreload" href="/assets/lock.html.b5f41d84.js"><link rel="modulepreload" href="/assets/plugin-vue_export-helper.21dcd24c.js"><link rel="modulepreload" href="/assets/lock.html.5385ecc8.js">
</head>
<body>
<div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc"><!--[--><!--[--><header class="navbar"><div class="navbar-left"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!----><a href="/" class="brand"><img class="logo" src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/logo-02.png" alt="Java 程序员进阶之路"><!----><span class="site-name hide-in-pad">Java 程序员进阶之路</span></a><!----></div><div class="navbar-center"><!----><nav class="nav-links"><div class="nav-item hide-in-mobile"><a href="/blog.html" class="nav-link" aria-label="博客"><span class="icon iconfont icon-gaishu" style=""></span>博客<!----></a></div><div class="nav-item hide-in-mobile"><a href="/home.html" class="nav-link" aria-label="进阶之路"><span class="icon iconfont icon-lujing" style=""></span>进阶之路<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zhishixingqiu/" class="nav-link" aria-label="知识星球"><span class="icon iconfont icon-Artboard" style=""></span>知识星球<!----></a></div><div class="nav-item hide-in-mobile"><a href="/xuexiluxian/" class="nav-link" aria-label="学习路线"><span class="icon iconfont icon-luxian" style=""></span>学习路线<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="珍藏资源"><span class="title"><span class="icon iconfont icon-youzhi" style=""></span>珍藏资源</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/download/java.html" class="nav-link" aria-label="电子书下载"><span class="icon iconfont icon-java" style=""></span>电子书下载<!----></a></li><li class="dropdown-item"><a href="/sidebar/sanfene/nixi.html" class="nav-link" aria-label="面渣逆袭"><span class="icon iconfont icon-zhunbei" style=""></span>面渣逆袭<!----></a></li><li class="dropdown-item"><a href="/download/nicearticle.html" class="nav-link" aria-label="优质文章"><span class="icon iconfont icon-youzhi" style=""></span>优质文章<!----></a></li><li class="dropdown-item"><a href="/download/history.html" class="nav-link" aria-label="网络日志"><span class="icon iconfont icon-rizhi" style=""></span>网络日志<!----></a></li><li class="dropdown-item"><a href="/nice-article/itmind/" class="nav-link" aria-label="破解合集"><span class="icon iconfont icon-zhongyaotishi" style=""></span>破解合集<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><a href="https://space.bilibili.com/513340480" rel="noopener noreferrer" target="_blank" aria-label="B站视频" class="nav-link"><span class="icon iconfont icon-bzhan" style=""></span>B站视频<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div></nav><!----></div><div class="navbar-right"><!----><div class="nav-item"><!----></div><div class="nav-item"><a class="repo-link" href="https://github.com/itwanger/toBeBetterJavaer" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="github icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></svg></a></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><div id="docsearch-container"></div><!----><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><!--[--><a href="/home.html" class="nav-link sidebar-link sidebar-page" aria-label="一、前言"><!---->一、前言<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">二、Java核心</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.1 Java概述</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.2 Java语法基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.3 数组&字符串</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.4 面向对象编程</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.5 集合框架(容器)</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.6 IO</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.7 异常处理</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.8 常用工具类</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.9 Java新特性</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.10 Java重要知识点</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">2.11 并发编程</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/thread/wangzhe-thread.html" class="nav-link sidebar-link sidebar-page" aria-label="创建Java线程的3种方式"><!---->创建Java线程的3种方式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/thread-state-and-method.html" class="nav-link sidebar-link sidebar-page" aria-label="线程的6种状态及切换"><!---->线程的6种状态及切换<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/thread-group-and-thread-priority.html" class="nav-link sidebar-link sidebar-page" aria-label="线程组和线程优先级"><!---->线程组和线程优先级<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/why-need-thread.html" class="nav-link sidebar-link sidebar-page" aria-label="进程与线程的区别"><!---->进程与线程的区别<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/thread-bring-some-problem.html" class="nav-link sidebar-link sidebar-page" aria-label="并发编程带来了哪些问题"><!---->并发编程带来了哪些问题<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/jmm.html" class="nav-link sidebar-link sidebar-page" aria-label="Java内存模型"><!---->Java内存模型<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/volatile.html" class="nav-link sidebar-link sidebar-page" aria-label="volatile"><!---->volatile<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/synchronized.html" class="nav-link sidebar-link sidebar-page" aria-label="synchronized"><!---->synchronized<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/cas.html" class="nav-link sidebar-link sidebar-page" aria-label="CAS的原理"><!---->CAS的原理<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/aqs.html" class="nav-link sidebar-link sidebar-page" aria-label="AQS详解"><!---->AQS详解<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/thread/lock.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" aria-label="锁"><!---->锁<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#synchronized的不足之处" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="synchronized的不足之处"><!---->synchronized的不足之处<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#锁的几种分类" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="锁的几种分类"><!---->锁的几种分类<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#可重入锁和非可重入锁" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="可重入锁和非可重入锁"><!---->可重入锁和非可重入锁<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#公平锁与非公平锁" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="公平锁与非公平锁"><!---->公平锁与非公平锁<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#读写锁和排它锁" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="读写锁和排它锁"><!---->读写锁和排它锁<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#jdk中有关锁的一些接口和类" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="JDK中有关锁的一些接口和类"><!---->JDK中有关锁的一些接口和类<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#抽象类aqs-aqls-aos" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="抽象类AQS/AQLS/AOS"><!---->抽象类AQS/AQLS/AOS<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#接口condition-lock-readwritelock" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="接口Condition/Lock/ReadWriteLock"><!---->接口Condition/Lock/ReadWriteLock<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#reentrantlock" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ReentrantLock"><!---->ReentrantLock<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#reentrantreadwritelock" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ReentrantReadWriteLock"><!---->ReentrantReadWriteLock<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/thread/lock.html#stampedlock" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="StampedLock"><!---->StampedLock<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li></ul><!--]--></li><li><!--[--><a href="/thread/reentrantLock.html" class="nav-link sidebar-link sidebar-page" aria-label="重入锁ReentrantLock"><!---->重入锁ReentrantLock<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ReentrantReadWriteLock.html" class="nav-link sidebar-link sidebar-page" aria-label="读写锁ReentrantReadWriteLock"><!---->读写锁ReentrantReadWriteLock<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/condition.html" class="nav-link sidebar-link sidebar-page" aria-label="线程协作类Condition"><!---->线程协作类Condition<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/LockSupport.html" class="nav-link sidebar-link sidebar-page" aria-label="线程阻塞唤醒类LockSupport"><!---->线程阻塞唤醒类LockSupport<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/map.html" class="nav-link sidebar-link sidebar-page" aria-label="并发集合容器"><!---->并发集合容器<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ConcurrentHashMap.html" class="nav-link sidebar-link sidebar-page" aria-label="ConcurrentHashMap"><!---->ConcurrentHashMap<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ConcurrentLinkedQueue.html" class="nav-link sidebar-link sidebar-page" aria-label="ConcurrentLinkedQueue"><!---->ConcurrentLinkedQueue<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/CopyOnWriteArrayList.html" class="nav-link sidebar-link sidebar-page" aria-label="CopyOnWriteArrayList"><!---->CopyOnWriteArrayList<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ThreadLocal.html" class="nav-link sidebar-link sidebar-page" aria-label="ThreadLocal"><!---->ThreadLocal<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/BlockingQueue.html" class="nav-link sidebar-link sidebar-page" aria-label="BlockingQueue"><!---->BlockingQueue<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/pool.html" class="nav-link sidebar-link sidebar-page" aria-label="线程池"><!---->线程池<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/ScheduledThreadPoolExecutor.html" class="nav-link sidebar-link sidebar-page" aria-label="计划任务"><!---->计划任务<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/atomic.html" class="nav-link sidebar-link sidebar-page" aria-label="原子操作类"><!---->原子操作类<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/CountDownLatch.html" class="nav-link sidebar-link sidebar-page" aria-label="通信工具类CountDownLatch"><!---->通信工具类CountDownLatch<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/fork-join.html" class="nav-link sidebar-link sidebar-page" aria-label="Fork/Join框架"><!---->Fork/Join框架<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/thread/shengchanzhe-xiaofeizhe.html" class="nav-link sidebar-link sidebar-page" aria-label="生产者-消费者模式"><!---->生产者-消费者模式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">2.12 JVM</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">三、Java企业级开发</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">四、数据库</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">五、计算机基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">六、求职面试</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">七、学习资源</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">八、学习建议</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">九、知识库搭建</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><!----><span class="title">十、联系作者</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!---->大致了解下Java的锁接口和锁</h1><div class="page-info"><span class="author-info" aria-label="作者🖊" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon author-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="author icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"></path></svg><span><a class="author-item" href="/about-the-author/" target="_blank" rel="noopener noreferrer">沉默王二</a></span><span property="author" content="沉默王二"></span></span><!----><span class="date-info" aria-label="写作日期📅" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="calendar icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></svg><span>2022年3月23日</span><meta property="datePublished" content="2022-03-23T12:08:58.000Z"></span><span class="category-info" aria-label="分类🌈" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon category-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="category icon"><path d="M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"></path></svg><ul class="categories-wrapper"><li class="category category0 clickable" role="navigation">Java核心</li><li class="category category6 clickable" role="navigation">并发编程</li><meta property="articleSection" content="Java核心,并发编程"></ul></span><span aria-label="标签🏷" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon tag-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="tag icon"><path d="M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"></path></svg><ul class="tags-wrapper"><li class="tag tag4 clickable" role="navigation">Java</li></ul><meta property="keywords" content="Java"></span><span class="reading-time-info" aria-label="阅读时间⌛" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 12 分钟</span><meta property="timeRequired" content="PT12M"></span></div><hr></div><div class="toc-place-holder"><aside id="toc"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#synchronized的不足之处" class="router-link-active router-link-exact-active toc-link level2">synchronized的不足之处</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#锁的几种分类" class="router-link-active router-link-exact-active toc-link level2">锁的几种分类</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#可重入锁和非可重入锁" class="router-link-active router-link-exact-active toc-link level3">可重入锁和非可重入锁</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#公平锁与非公平锁" class="router-link-active router-link-exact-active toc-link level3">公平锁与非公平锁</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#读写锁和排它锁" class="router-link-active router-link-exact-active toc-link level3">读写锁和排它锁</a></li><!----><!--]--></ul><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#jdk中有关锁的一些接口和类" class="router-link-active router-link-exact-active toc-link level2">JDK中有关锁的一些接口和类</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#抽象类aqs-aqls-aos" class="router-link-active router-link-exact-active toc-link level3">抽象类AQS/AQLS/AOS</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#接口condition-lock-readwritelock" class="router-link-active router-link-exact-active toc-link level3">接口Condition/Lock/ReadWriteLock</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#reentrantlock" class="router-link-active router-link-exact-active toc-link level3">ReentrantLock</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#reentrantreadwritelock" class="router-link-active router-link-exact-active toc-link level3">ReentrantReadWriteLock</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/thread/lock.html#stampedlock" class="router-link-active router-link-exact-active toc-link level3">StampedLock</a></li><!----><!--]--></ul><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><h1 id="大致了解下java的锁接口和锁" tabindex="-1"><a class="header-anchor" href="#大致了解下java的锁接口和锁" aria-hidden="true">#</a> 大致了解下Java的锁接口和锁</h1><p>前面我们介绍了Java原生的锁——基于对象的锁,它一般是配合synchronized关键字来使用的。实际上,Java在<code>java.util.concurrent.locks</code>包下,还为我们提供了几个关于锁的类和接口。它们有更强大的功能或更高的性能。</p><h2 id="synchronized的不足之处" tabindex="-1"><a class="header-anchor" href="#synchronized的不足之处" aria-hidden="true">#</a> synchronized的不足之处</h2><p>我们先来看看<code>synchronized</code>有什么不足之处。</p><ul><li>如果临界区是只读操作,其实可以多线程一起执行,但使用synchronized的话,<strong>同一时间只能有一个线程执行</strong>。</li><li>synchronized无法知道线程有没有成功获取到锁</li><li>使用synchronized,如果临界区因为IO或者sleep方法等原因阻塞了,而当前线程又没有释放锁,就会导致<strong>所有线程等待</strong>。</li></ul><p>而这些都是locks包下的锁可以解决的。</p><h2 id="锁的几种分类" tabindex="-1"><a class="header-anchor" href="#锁的几种分类" aria-hidden="true">#</a> 锁的几种分类</h2><p>锁可以根据以下几种方式来进行分类,下面我们逐一介绍。</p><h3 id="可重入锁和非可重入锁" tabindex="-1"><a class="header-anchor" href="#可重入锁和非可重入锁" aria-hidden="true">#</a> 可重入锁和非可重入锁</h3><p>所谓重入锁,顾名思义。就是支持重新进入的锁,也就是说这个锁支持一个<strong>线程对资源重复加锁</strong>。</p><p>synchronized关键字就是使用的重入锁。比如说,你在一个synchronized实例方法里面调用另一个本实例的synchronized实例方法,它可以重新进入这个锁,不会出现任何异常。</p><p>如果我们自己在继承AQS实现同步器的时候,没有考虑到占有锁的线程再次获取锁的场景,可能就会导致线程阻塞,那这个就是一个“非可重入锁”。</p><p><code>ReentrantLock</code>的中文意思就是可重入锁。也是本文后续要介绍的重点类。</p><h3 id="公平锁与非公平锁" tabindex="-1"><a class="header-anchor" href="#公平锁与非公平锁" aria-hidden="true">#</a> 公平锁与非公平锁</h3><p>这里的“公平”,其实通俗意义来说就是“先来后到”,也就是FIFO。如果对一个锁来说,先对锁获取请求的线程一定会先被满足,后对锁获取请求的线程后被满足,那这个锁就是公平的。反之,那就是不公平的。</p><p>一般情况下,<strong>非公平锁能提升一定的效率。但是非公平锁可能会发生线程饥饿(有一些线程长时间得不到锁)的情况</strong>。所以要根据实际的需求来选择非公平锁和公平锁。</p><p>ReentrantLock支持非公平锁和公平锁两种。</p><h3 id="读写锁和排它锁" tabindex="-1"><a class="header-anchor" href="#读写锁和排它锁" aria-hidden="true">#</a> 读写锁和排它锁</h3><p>我们前面讲到的synchronized用的锁和ReentrantLock,其实都是“排它锁”。也就是说,这些锁在同一时刻只允许一个线程进行访问。</p><p>而读写锁可以在同一时刻允许多个读线程访问。Java提供了ReentrantReadWriteLock类作为读写锁的默认实现,内部维护了两个锁:一个读锁,一个写锁。通过分离读锁和写锁,使得在“读多写少”的环境下,大大地提高了性能。</p><blockquote><p>注意,即使用读写锁,在写线程访问时,所有的读线程和其它写线程均被阻塞。</p></blockquote><p><strong>可见,只是synchronized是远远不能满足多样化的业务对锁的要求的</strong>。接下来我们介绍一下JDK中有关锁的一些接口和类。</p><h2 id="jdk中有关锁的一些接口和类" tabindex="-1"><a class="header-anchor" href="#jdk中有关锁的一些接口和类" aria-hidden="true">#</a> JDK中有关锁的一些接口和类</h2><p>众所周知,JDK中关于并发的类大多都在<code>java.util.concurrent</code>(以下简称juc)包下。而juc.locks包看名字就知道,是提供了一些并发锁的工具类的。前面我们介绍的AQS(AbstractQueuedSynchronizer)就是在这个包下。下面分别介绍一下这个包下的类和接口以及它们之间的关系。</p><h3 id="抽象类aqs-aqls-aos" tabindex="-1"><a class="header-anchor" href="#抽象类aqs-aqls-aos" aria-hidden="true">#</a> 抽象类AQS/AQLS/AOS</h3><p>这三个抽象类有一定的关系,所以这里放到一起讲。</p><p>首先我们看<strong>AQS</strong>(AbstractQueuedSynchronizer),之前专门有章节介绍这个类,它是在JDK 1.5 发布的,提供了一个“队列同步器”的基本功能实现。而AQS里面的“资源”是用一个<code>int</code>类型的数据来表示的,有时候我们的业务需求资源的数量超出了<code>int</code>的范围,所以在JDK 1.6 中,多了一个<strong>AQLS</strong>(AbstractQueuedLongSynchronizer)。它的代码跟AQS几乎一样,只是把资源的类型变成了<code>long</code>类型。</p><p>AQS和AQLS都继承了一个类叫<strong>AOS</strong>(AbstractOwnableSynchronizer)。这个类也是在JDK 1.6 中出现的。这个类只有几行简单的代码。从源码类上的注释可以知道,它是用于表示锁与持有者之间的关系(独占模式)。可以看一下它的主要方法:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// 独占模式,锁的持有者 </span>
<span class="token keyword">private</span> <span class="token keyword">transient</span> <span class="token class-name">Thread</span> exclusiveOwnerThread<span class="token punctuation">;</span>
<span class="token comment">// 设置锁持有者 </span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">setExclusiveOwnerThread</span><span class="token punctuation">(</span><span class="token class-name">Thread</span> t<span class="token punctuation">)</span> <span class="token punctuation">{</span>
exclusiveOwnerThread <span class="token operator">=</span> t<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 获取锁的持有线程 </span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token class-name">Thread</span> <span class="token function">getExclusiveOwnerThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> exclusiveOwnerThread<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="接口condition-lock-readwritelock" tabindex="-1"><a class="header-anchor" href="#接口condition-lock-readwritelock" aria-hidden="true">#</a> 接口Condition/Lock/ReadWriteLock</h3><p>juc.locks包下共有三个接口:<code>Condition</code>、<code>Lock</code>、<code>ReadWriteLock</code>。其中,Lock和ReadWriteLock从名字就可以看得出来,分别是锁和读写锁的意思。Lock接口里面有一些获取锁和释放锁的方法声明,而ReadWriteLock里面只有两个方法,分别返回“读锁”和“写锁”:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">ReadWriteLock</span> <span class="token punctuation">{</span>
<span class="token class-name">Lock</span> <span class="token function">readLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Lock</span> <span class="token function">writeLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Lock接口中有一个方法是可以获得一个<code>Condition</code>:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">Condition</span> <span class="token function">newCondition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>之前我们提到了每个对象都可以用继承自<code>Object</code>的<strong>wait/notify</strong>方法来实现<strong>等待/通知机制</strong>。而Condition接口也提供了类似Object监视器的方法,通过与<strong>Lock</strong>配合来实现等待/通知模式。</p><p>那为什么既然有Object的监视器方法了,还要用Condition呢?这里有一个二者简单的对比:</p><table><thead><tr><th>对比项</th><th>Object监视器</th><th>Condition</th></tr></thead><tbody><tr><td>前置条件</td><td>获取对象的锁</td><td>调用Lock.lock获取锁,调用Lock.newCondition获取Condition对象</td></tr><tr><td>调用方式</td><td>直接调用,比如object.notify()</td><td>直接调用,比如condition.await()</td></tr><tr><td>等待队列的个数</td><td>一个</td><td>多个</td></tr><tr><td>当前线程释放锁进入等待状态</td><td>支持</td><td>支持</td></tr><tr><td>当前线程释放锁进入等待状态,在等待状态中不中断</td><td>不支持</td><td>支持</td></tr><tr><td>当前线程释放锁并进入超时等待状态</td><td>支持</td><td>支持</td></tr><tr><td>当前线程释放锁并进入等待状态直到将来的某个时间</td><td>不支持</td><td>支持</td></tr><tr><td>唤醒等待队列中的一个线程</td><td>支持</td><td>支持</td></tr><tr><td>唤醒等待队列中的全部线程</td><td>支持</td><td>支持</td></tr></tbody></table><p>Condition和Object的wait/notify基本相似。其中,Condition的await方法对应的是Object的wait方法,而Condition的<strong>signal/signalAll</strong>方法则对应Object的notify/notifyAll()。但Condition类似于Object的等待/通知机制的加强版。我们来看看主要的方法:</p><table><thead><tr><th>方法名称</th><th>描述</th></tr></thead><tbody><tr><td>await()</td><td>当前线程进入等待状态直到被通知(signal)或者中断;当前线程进入运行状态并从await()方法返回的场景包括:(1)其他线程调用相同Condition对象的signal/signalAll方法,并且当前线程被唤醒;(2)其他线程调用interrupt方法中断当前线程;</td></tr><tr><td>awaitUninterruptibly()</td><td>当前线程进入等待状态直到被通知,在此过程中对中断信号不敏感,不支持中断当前线程</td></tr><tr><td>awaitNanos(long)</td><td>当前线程进入等待状态,直到被通知、中断或者超时。如果返回值小于等于0,可以认定就是超时了</td></tr><tr><td>awaitUntil(Date)</td><td>当前线程进入等待状态,直到被通知、中断或者超时。如果没到指定时间被通知,则返回true,否则返回false</td></tr><tr><td>signal()</td><td>唤醒一个等待在Condition上的线程,被唤醒的线程在方法返回前必须获得与Condition对象关联的锁</td></tr><tr><td>signalAll()</td><td>唤醒所有等待在Condition上的线程,能够从await()等方法返回的线程必须先获得与Condition对象关联的锁</td></tr></tbody></table><h3 id="reentrantlock" tabindex="-1"><a class="header-anchor" href="#reentrantlock" aria-hidden="true">#</a> ReentrantLock</h3><p>ReentrantLock是一个非抽象类,它是Lock接口的JDK默认实现,实现了锁的基本功能。从名字上看,它是一个”可重入“锁,从源码上看,它内部有一个抽象类<code>Sync</code>,是继承了AQS,自己实现的一个同步器。同时,ReentrantLock内部有两个非抽象类<code>NonfairSync</code>和<code>FairSync</code>,它们都继承了Sync。从名字上看得出,分别是”非公平同步器“和”公平同步器“的意思。这意味着ReentrantLock可以支持”公平锁“和”非公平锁“。</p><p>通过看这两个同步器的源码可以发现,它们的实现都是”独占“的。都调用了AOS的<code>setExclusiveOwnerThread</code>方法,所以ReentrantLock的锁是”独占“的,也就是说,它的锁都是”排他锁“,不能共享。</p><p>在ReentrantLock的构造方法里,可以传入一个<code>boolean</code>类型的参数,来指定它是否是一个公平锁,默认情况下是非公平的。这个参数一旦实例化后就不能修改,只能通过<code>isFair()</code>方法来查看。</p><h3 id="reentrantreadwritelock" tabindex="-1"><a class="header-anchor" href="#reentrantreadwritelock" aria-hidden="true">#</a> ReentrantReadWriteLock</h3><p>这个类也是一个非抽象类,它是ReadWriteLock接口的JDK默认实现。它与ReentrantLock的功能类似,同样是可重入的,支持非公平锁和公平锁。不同的是,它还支持”读写锁“。</p><p>ReentrantReadWriteLock内部的结构大概是这样:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// 内部结构</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">ReentrantReadWriteLock<span class="token punctuation">.</span>ReadLock</span> readerLock<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">ReentrantReadWriteLock<span class="token punctuation">.</span>WriteLock</span> writerLock<span class="token punctuation">;</span>
<span class="token keyword">final</span> <span class="token class-name">Sync</span> sync<span class="token punctuation">;</span>
<span class="token keyword">abstract</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Sync</span> <span class="token keyword">extends</span> <span class="token class-name">AbstractQueuedSynchronizer</span> <span class="token punctuation">{</span>
<span class="token comment">// 具体实现</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">NonfairSync</span> <span class="token keyword">extends</span> <span class="token class-name">Sync</span> <span class="token punctuation">{</span>
<span class="token comment">// 具体实现</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">FairSync</span> <span class="token keyword">extends</span> <span class="token class-name">Sync</span> <span class="token punctuation">{</span>
<span class="token comment">// 具体实现</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">ReadLock</span> <span class="token keyword">implements</span> <span class="token class-name">Lock</span><span class="token punctuation">,</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span>Serializable</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">Sync</span> sync<span class="token punctuation">;</span>
<span class="token keyword">protected</span> <span class="token class-name">ReadLock</span><span class="token punctuation">(</span><span class="token class-name">ReentrantReadWriteLock</span> lock<span class="token punctuation">)</span> <span class="token punctuation">{</span>
sync <span class="token operator">=</span> lock<span class="token punctuation">.</span>sync<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 具体实现</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">WriteLock</span> <span class="token keyword">implements</span> <span class="token class-name">Lock</span><span class="token punctuation">,</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span>Serializable</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">Sync</span> sync<span class="token punctuation">;</span>
<span class="token keyword">protected</span> <span class="token class-name">WriteLock</span><span class="token punctuation">(</span><span class="token class-name">ReentrantReadWriteLock</span> lock<span class="token punctuation">)</span> <span class="token punctuation">{</span>
sync <span class="token operator">=</span> lock<span class="token punctuation">.</span>sync<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 具体实现</span>
<span class="token punctuation">}</span>
<span class="token comment">// 构造方法,初始化两个锁</span>
<span class="token keyword">public</span> <span class="token class-name">ReentrantReadWriteLock</span><span class="token punctuation">(</span><span class="token keyword">boolean</span> fair<span class="token punctuation">)</span> <span class="token punctuation">{</span>
sync <span class="token operator">=</span> fair <span class="token operator">?</span> <span class="token keyword">new</span> <span class="token class-name">FairSync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">NonfairSync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
readerLock <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReadLock</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
writerLock <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">WriteLock</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 获取读锁和写锁的方法</span>
<span class="token keyword">public</span> <span class="token class-name">ReentrantReadWriteLock<span class="token punctuation">.</span>WriteLock</span> <span class="token function">writeLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> writerLock<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">ReentrantReadWriteLock<span class="token punctuation">.</span>ReadLock</span> <span class="token function">readLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> readerLock<span class="token punctuation">;</span> <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以看到,它同样是内部维护了两个同步器。且维护了两个Lock的实现类ReadLock和WriteLock。从源码可以发现,这两个内部类用的是外部类的同步器。</p><p>ReentrantReadWriteLock实现了读写锁,但它有一个小弊端,就是在“写”操作的时候,其它线程不能写也不能读。我们称这种现象为“写饥饿”,将在后文的StampedLock类继续讨论这个问题。</p><h3 id="stampedlock" tabindex="-1"><a class="header-anchor" href="#stampedlock" aria-hidden="true">#</a> StampedLock</h3><p><code>StampedLock</code>类是在Java 8 才发布的,也是Doug Lea大神所写,有人号称它为锁的性能之王。它没有实现Lock接口和ReadWriteLock接口,但它其实是实现了“读写锁”的功能,并且性能比ReentrantReadWriteLock更高。StampedLock还把读锁分为了“乐观读锁”和“悲观读锁”两种。</p><p>前面提到了ReentrantReadWriteLock会发生“写饥饿”的现象,但StampedLock不会。它是怎么做到的呢?它的核心思想在于,<strong>在读的时候如果发生了写,应该通过重试的方式来获取新的值,而不应该阻塞写操作。这种模式也就是典型的无锁编程思想,和CAS自旋的思想一样</strong>。这种操作方式决定了StampedLock在读线程非常多而写线程非常少的场景下非常适用,同时还避免了写饥饿情况的发生。</p><p>这里篇幅有限,就不介绍StampedLock的源码了,只是分析一下官方提供的用法(在JDK源码类声明的上方或Javadoc里可以找到)。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">class</span> <span class="token class-name">Point</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">double</span> x<span class="token punctuation">,</span> y<span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">StampedLock</span> sl <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StampedLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 写锁的使用</span>
<span class="token keyword">void</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token keyword">double</span> deltaX<span class="token punctuation">,</span> <span class="token keyword">double</span> deltaY<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> stamp <span class="token operator">=</span> sl<span class="token punctuation">.</span><span class="token function">writeLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 获取写锁</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
x <span class="token operator">+=</span> deltaX<span class="token punctuation">;</span>
y <span class="token operator">+=</span> deltaY<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
sl<span class="token punctuation">.</span><span class="token function">unlockWrite</span><span class="token punctuation">(</span>stamp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 释放写锁</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// 乐观读锁的使用</span>
<span class="token keyword">double</span> <span class="token function">distanceFromOrigin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> stamp <span class="token operator">=</span> sl<span class="token punctuation">.</span><span class="token function">tryOptimisticRead</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 获取乐观读锁</span>
<span class="token keyword">double</span> currentX <span class="token operator">=</span> x<span class="token punctuation">,</span> currentY <span class="token operator">=</span> y<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>sl<span class="token punctuation">.</span><span class="token function">validate</span><span class="token punctuation">(</span>stamp<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// //检查乐观读锁后是否有其他写锁发生,有则返回false</span>
stamp <span class="token operator">=</span> sl<span class="token punctuation">.</span><span class="token function">readLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 获取一个悲观读锁</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
currentX <span class="token operator">=</span> x<span class="token punctuation">;</span>
currentY <span class="token operator">=</span> y<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
sl<span class="token punctuation">.</span><span class="token function">unlockRead</span><span class="token punctuation">(</span>stamp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 释放悲观读锁</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">sqrt</span><span class="token punctuation">(</span>currentX <span class="token operator">*</span> currentX <span class="token operator">+</span> currentY <span class="token operator">*</span> currentY<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 悲观读锁以及读锁升级写锁的使用</span>
<span class="token keyword">void</span> <span class="token function">moveIfAtOrigin</span><span class="token punctuation">(</span><span class="token keyword">double</span> newX<span class="token punctuation">,</span> <span class="token keyword">double</span> newY<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> stamp <span class="token operator">=</span> sl<span class="token punctuation">.</span><span class="token function">readLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 悲观读锁</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>x <span class="token operator">==</span> <span class="token number">0.0</span> <span class="token operator">&&</span> y <span class="token operator">==</span> <span class="token number">0.0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 读锁尝试转换为写锁:转换成功后相当于获取了写锁,转换失败相当于有写锁被占用</span>
<span class="token keyword">long</span> ws <span class="token operator">=</span> sl<span class="token punctuation">.</span><span class="token function">tryConvertToWriteLock</span><span class="token punctuation">(</span>stamp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ws <span class="token operator">!=</span> <span class="token number">0L</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 如果转换成功</span>
stamp <span class="token operator">=</span> ws<span class="token punctuation">;</span> <span class="token comment">// 读锁的票据更新为写锁的</span>
x <span class="token operator">=</span> newX<span class="token punctuation">;</span>
y <span class="token operator">=</span> newY<span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// 如果转换失败</span>
sl<span class="token punctuation">.</span><span class="token function">unlockRead</span><span class="token punctuation">(</span>stamp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 释放读锁</span>
stamp <span class="token operator">=</span> sl<span class="token punctuation">.</span><span class="token function">writeLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 强制获取写锁</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
sl<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span>stamp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 释放所有锁</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote><p>乐观读锁的意思就是先假定在这个锁获取期间,共享变量不会被改变,既然假定不会被改变,那就不需要上锁。在获取乐观读锁之后进行了一些操作,然后又调用了validate方法,这个方法就是用来验证tryOptimisticRead之后,是否有写操作执行过,如果有,则获取一个悲观读锁,这里的悲观读锁和ReentrantReadWriteLock中的读锁类似,也是个共享锁。</p></blockquote><p>可以看到,StampedLock获取锁会返回一个<code>long</code>类型的变量,释放锁的时候再把这个变量传进去。简单看看源码:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">// 用于操作state后获取stamp的值</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> LG_READERS <span class="token operator">=</span> <span class="token number">7</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> RUNIT <span class="token operator">=</span> <span class="token number">1L</span><span class="token punctuation">;</span> <span class="token comment">//0000 0000 0001</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> WBIT <span class="token operator">=</span> <span class="token number">1L</span> <span class="token operator"><<</span> LG_READERS<span class="token punctuation">;</span> <span class="token comment">//0000 1000 0000</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> RBITS <span class="token operator">=</span> WBIT <span class="token operator">-</span> <span class="token number">1L</span><span class="token punctuation">;</span> <span class="token comment">//0000 0111 1111</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> RFULL <span class="token operator">=</span> RBITS <span class="token operator">-</span> <span class="token number">1L</span><span class="token punctuation">;</span> <span class="token comment">//0000 0111 1110</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> ABITS <span class="token operator">=</span> RBITS <span class="token operator">|</span> WBIT<span class="token punctuation">;</span> <span class="token comment">//0000 1111 1111</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> SBITS <span class="token operator">=</span> <span class="token operator">~</span>RBITS<span class="token punctuation">;</span> <span class="token comment">//1111 1000 0000</span>
<span class="token comment">// 初始化时state的值</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> ORIGIN <span class="token operator">=</span> WBIT <span class="token operator"><<</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">//0001 0000 0000</span>
<span class="token comment">// 锁共享变量state</span>
<span class="token keyword">private</span> <span class="token keyword">transient</span> <span class="token keyword">volatile</span> <span class="token keyword">long</span> state<span class="token punctuation">;</span>
<span class="token comment">// 读锁溢出时用来存储多出的读锁</span>
<span class="token keyword">private</span> <span class="token keyword">transient</span> <span class="token keyword">int</span> readerOverflow<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>StampedLock用这个long类型的变量的前7位(LG_READERS)来表示读锁,每获取一个悲观读锁,就加1(RUNIT),每释放一个悲观读锁,就减1。而悲观读锁最多只能装128个(7位限制),很容易溢出,所以用一个int类型的变量来存储溢出的悲观读锁。</p><p>写锁用state变量剩下的位来表示,每次获取一个写锁,就加0000 1000 0000(WBIT)。需要注意的是,<strong>写锁在释放的时候,并不是减WBIT,而是再加WBIT</strong>。这是为了<strong>让每次写锁都留下痕迹</strong>,解决CAS中的ABA问题,也为<strong>乐观锁检查变化</strong>validate方法提供基础。</p><p>乐观读锁就比较简单了,并没有真正改变state的值,而是在获取锁的时候记录state的写状态,在操作完成后去检查state的写状态部分是否发生变化,上文提到了,每次写锁都会留下痕迹,也是为了这里乐观锁检查变化提供方便。</p><p>总的来说,StampedLock的性能是非常优异的,基本上可以取代ReentrantReadWriteLock的作用。</p><hr><blockquote><p>编辑:沉默王二,内容大部分来源以下三个开源仓库:</p><ul><li><a href="http://concurrent.redspider.group/" target="_blank" rel="noopener noreferrer">深入浅出 Java 多线程<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li><a href="https://github.com/CL0610/Java-concurrency" target="_blank" rel="noopener noreferrer">并发编程知识总结<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li><a href="https://github.com/CoderLeixiaoshuai/java-eight-part" target="_blank" rel="noopener noreferrer">Java八股文<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li></ul></blockquote><img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png"></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://github.com/itwanger/toBeBetterJavaer/edit/master/docs/thread/lock.md" rel="noopener noreferrer" target="_blank" aria-label="在 GitHub 上编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->在 GitHub 上编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="meta-item update-time"><span class="label">上次编辑于: </span><span class="info">2022/3/27 下午4:36:50</span></div><div class="meta-item contributors"><span class="label">贡献者: </span><!--[--><!--[--><span class="contributor" title="email: [email protected]">itwanger</span><!--]--><!--]--></div></footer><nav class="page-nav"><a href="/thread/aqs.html" class="nav-link prev" aria-label="AQS详解"><div class="hint"><span class="arrow left"></span>上一页</div><div class="link"><!---->AQS详解</div></a><a href="/thread/reentrantLock.html" class="nav-link next" aria-label="重入锁ReentrantLock"><div class="hint">下一页<span class="arrow right"></span></div><div class="link">重入锁ReentrantLock<!----></div></a></nav><div class="giscus-wrapper input-top" style="display:block;">Loading...</div><!----><!--]--></main><!--]--><footer class="footer-wrapper"><div class="footer"><a href="https://beian.miit.gov.cn/" target="_blank">豫ICP备2021038026号-1</a><img src="https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/beian.png" height="15px" width="15px" /><a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=41030502000411"><span>豫公网安备 41030502000411号</span></a></div><div class="copyright">Copyright © 2022 沉默王二</div></footer><!--]--></div><!--]--><!----><!----><!--]--></div>
<script type="module" src="/assets/app.41bad062.js" defer></script>
</body>
</html>