Skip to content

Commit 21cfce6

Browse files
author
wangyueyang
committed
锁的模型与设计
1 parent 15edda4 commit 21cfce6

2 files changed

Lines changed: 469 additions & 0 deletions

File tree

‎java/lockModel.html‎

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
5+
<head>
6+
<title>锁的设计模型</title>
7+
<!-- 2017-10-12 周四 10:36 -->
8+
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
9+
<meta name="generator" content="Org-mode" />
10+
<meta name="author" content="王月阳" />
11+
<meta name="description" content="单机或者分布式环境中,锁的模型与设计"
12+
/>
13+
<meta name="keywords" content="Java concurrenty 多线程 AQS Java锁 资源争用" />
14+
<style type="text/css">
15+
<!--/*--><![CDATA[/*><!--*/
16+
.title { text-align: center; }
17+
.todo { font-family: monospace; color: red; }
18+
.done { color: green; }
19+
.tag { background-color: #eee; font-family: monospace;
20+
padding: 2px; font-size: 80%; font-weight: normal; }
21+
.timestamp { color: #bebebe; }
22+
.timestamp-kwd { color: #5f9ea0; }
23+
.right { margin-left: auto; margin-right: 0px; text-align: right; }
24+
.left { margin-left: 0px; margin-right: auto; text-align: left; }
25+
.center { margin-left: auto; margin-right: auto; text-align: center; }
26+
.underline { text-decoration: underline; }
27+
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
28+
p.verse { margin-left: 3%; }
29+
pre {
30+
border: 1px solid #ccc;
31+
box-shadow: 3px 3px 3px #eee;
32+
padding: 8pt;
33+
font-family: monospace;
34+
overflow: auto;
35+
margin: 1.2em;
36+
}
37+
pre.src {
38+
position: relative;
39+
overflow: visible;
40+
padding-top: 1.2em;
41+
}
42+
pre.src:before {
43+
display: none;
44+
position: absolute;
45+
background-color: white;
46+
top: -10px;
47+
right: 10px;
48+
padding: 3px;
49+
border: 1px solid black;
50+
}
51+
pre.src:hover:before { display: inline;}
52+
pre.src-sh:before { content: 'sh'; }
53+
pre.src-bash:before { content: 'sh'; }
54+
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
55+
pre.src-R:before { content: 'R'; }
56+
pre.src-perl:before { content: 'Perl'; }
57+
pre.src-java:before { content: 'Java'; }
58+
pre.src-sql:before { content: 'SQL'; }
59+
60+
table { border-collapse:collapse; }
61+
caption.t-above { caption-side: top; }
62+
caption.t-bottom { caption-side: bottom; }
63+
td, th { vertical-align:top; }
64+
th.right { text-align: center; }
65+
th.left { text-align: center; }
66+
th.center { text-align: center; }
67+
td.right { text-align: right; }
68+
td.left { text-align: left; }
69+
td.center { text-align: center; }
70+
dt { font-weight: bold; }
71+
.footpara:nth-child(2) { display: inline; }
72+
.footpara { display: block; }
73+
.footdef { margin-bottom: 1em; }
74+
.figure { padding: 1em; }
75+
.figure p { text-align: center; }
76+
.inlinetask {
77+
padding: 10px;
78+
border: 2px solid gray;
79+
margin: 10px;
80+
background: #ffffcc;
81+
}
82+
#org-div-home-and-up
83+
{ text-align: right; font-size: 70%; white-space: nowrap; }
84+
textarea { overflow-x: auto; }
85+
.linenr { font-size: smaller }
86+
.code-highlighted { background-color: #ffff00; }
87+
.org-info-js_info-navigation { border-style: none; }
88+
#org-info-js_console-label
89+
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
90+
.org-info-js_search-highlight
91+
{ background-color: #ffff00; color: #000000; font-weight: bold; }
92+
/*]]>*/-->
93+
</style>
94+
<link rel="stylesheet" type="text/css" href="./css/style.css" />
95+
<script type="text/javascript">
96+
/*
97+
@licstart The following is the entire license notice for the
98+
JavaScript code in this tag.
99+
100+
Copyright (C) 2012-2013 Free Software Foundation, Inc.
101+
102+
The JavaScript code in this tag is free software: you can
103+
redistribute it and/or modify it under the terms of the GNU
104+
General Public License (GNU GPL) as published by the Free Software
105+
Foundation, either version 3 of the License, or (at your option)
106+
any later version. The code is distributed WITHOUT ANY WARRANTY;
107+
without even the implied warranty of MERCHANTABILITY or FITNESS
108+
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
109+
110+
As additional permission under GNU GPL version 3 section 7, you
111+
may distribute non-source (e.g., minimized or compacted) forms of
112+
that code without the copy of the GNU GPL normally required by
113+
section 4, provided you include this license notice and a URL
114+
through which recipients can access the Corresponding Source.
115+
116+
117+
@licend The above is the entire license notice
118+
for the JavaScript code in this tag.
119+
*/
120+
<!--/*--><![CDATA[/*><!--*/
121+
function CodeHighlightOn(elem, id)
122+
{
123+
var target = document.getElementById(id);
124+
if(null != target) {
125+
elem.cacheClassElem = elem.className;
126+
elem.cacheClassTarget = target.className;
127+
target.className = "code-highlighted";
128+
elem.className = "code-highlighted";
129+
}
130+
}
131+
function CodeHighlightOff(elem, id)
132+
{
133+
var target = document.getElementById(id);
134+
if(elem.cacheClassElem)
135+
elem.className = elem.cacheClassElem;
136+
if(elem.cacheClassTarget)
137+
target.className = elem.cacheClassTarget;
138+
}
139+
/*]]>*///-->
140+
</script>
141+
</head>
142+
<body>
143+
<div id="content">
144+
<h1 class="title">锁的设计模型</h1>
145+
<p>
146+
宣传一下我的qq群:412052579。里面有一些计算机相关的资料,不定期有人开讲。
147+
</p>
148+
149+
<p>
150+
锁是资源争用模型里面,排队模型的实现方式之一。建议先去了解一下资源争用模型,
151+
<a href="https://github.com/wyycode/java/blob/master/java/concurrency.org">临时blog地址</a>
152+
</p>
153+
154+
<p>
155+
一个锁的设计要考虑的包含如下几个方面:
156+
</p>
157+
<ol class="org-ol">
158+
<li>抽象资源状态的标志位
159+
</li>
160+
<li>对标志位的原子复合操作
161+
</li>
162+
<li>对争用者行为的控制,包括暂停和恢复
163+
</li>
164+
<li>对争用者的暂存功能
165+
</li>
166+
</ol>
167+
168+
<p>
169+
先理解我说的这四点
170+
</p>
171+
172+
<p>
173+
然后我再说分布式锁
174+
</p>
175+
176+
<p>
177+
原子复合操作就是底层工具提供的原子操作的原语
178+
</p>
179+
180+
<p>
181+
比如jvm给java提供的 cas
182+
</p>
183+
184+
<p>
185+
cpu给系统提供的内存屏障
186+
</p>
187+
188+
<p>
189+
硬件到系统,系统到vm,vm到语言,单机到分布式
190+
</p>
191+
192+
<p>
193+
都相当于底层为上层提供支持
194+
</p>
195+
196+
<p>
197+
不要傻傻的跟我从语言一步到硬件
198+
</p>
199+
200+
<p>
201+
系统依赖硬件提供的原子操作(数据结构)构建出系统级原语给vm/c语言用,vm依赖系统提供的原语构造出原子操作(数据结构)给java使用
202+
</p>
203+
204+
<p>
205+
单机到分布式也是一样的
206+
</p>
207+
208+
<p>
209+
锁要实现的功能就是要操作排队
210+
</p>
211+
212+
<p>
213+
操作的划分,在现有的系统中都是以线程为单位的
214+
</p>
215+
216+
<p>
217+
那么锁要实现的就是让线程排队
218+
</p>
219+
220+
<p>
221+
排队是做什么呢?我们讲一下生活中的排队
222+
</p>
223+
224+
<p>
225+
先来的操作资源,后来的人在 依次 等待,等前面的人 完成之后,恢复操作
226+
</p>
227+
228+
<p>
229+
这句话里有四个重点词语分别是
230+
</p>
231+
232+
<p>
233+
依次,等待,完成之后,恢复
234+
</p>
235+
236+
<p>
237+
隐含的一个点就是完成之后怎么通知等待者去操作资源的
238+
</p>
239+
240+
<p>
241+
我们来说一下这四个关键词
242+
</p>
243+
244+
<p>
245+
完成之后描述的是资源状态
246+
</p>
247+
248+
<p>
249+
在锁的设计中,我们一般用一个数字来抽象资源状态
250+
</p>
251+
252+
<p>
253+
比如0是空闲,1是被占用
254+
</p>
255+
256+
<p>
257+
依次是要保证线程先来后到的顺序
258+
</p>
259+
260+
<p>
261+
等待呢,是指不占用cpu
262+
</p>
263+
264+
<p>
265+
恢复是从排队的队列中唤醒下一个线程
266+
</p>
267+
268+
<p>
269+
jvm是怎么按照这四点来实现一个锁的呢?
270+
</p>
271+
272+
<p>
273+
首先用一个state字段抽象资源状态,这个字段是volatile的
274+
</p>
275+
276+
<p>
277+
然后,利用LockSupport.park功能实现线程等待
278+
</p>
279+
280+
<p>
281+
将等待的线程放置到CLH队列里
282+
</p>
283+
284+
<p>
285+
当占用资源的线程使用完成之后,会把state设置为空闲状态,并且利用LockSupport.unpark唤醒下一个线程
286+
</p>
287+
288+
<p>
289+
马上讲分布式锁
290+
</p>
291+
292+
<p>
293+
这就是jvm的单机锁
294+
</p>
295+
296+
<p>
297+
分布式锁与单机锁没有区别,只是资源不再是只存在单机中
298+
</p>
299+
300+
<p>
301+
也就是说,不是只有单机的线程会争用资源, 其他机器的线程也会争用资源
302+
</p>
303+
304+
<p>
305+
场景是,一个资源在多机共享
306+
</p>
307+
308+
<p>
309+
根据以上四点
310+
</p>
311+
312+
<p>
313+
我们需要一个多机都能读写的state数据
314+
</p>
315+
316+
<p>
317+
比如用redis来存这个state
318+
</p>
319+
320+
<p>
321+
然后,就跟单机一个实现线程等待,排队,唤醒
322+
</p>
323+
324+
<p>
325+
只是这个抽象的状态由多机的线程共同使用了而已
326+
</p>
327+
328+
<p>
329+
所以还是要先理解争用的资源是什么,争用者的范围是什么
330+
</p>
331+
332+
<p>
333+
如果争用者范围只是单机的,那么就可以用单机的一个state来抽象争用资源
334+
</p>
335+
336+
<p>
337+
如果范围是分布式的, 就需要用一个多机都能读写的state来抽象资源状态设计锁
338+
</p>
339+
340+
<p>
341+
其他的三点,因为都是jvm的线程,所以,都可以利用jvm的原子操作设计
342+
</p>
343+
344+
<p>
345+
所以,所谓的分布式锁,只是争用者范围扩展了而已
346+
</p>
347+
348+
<p>
349+
没什么特别的
350+
</p>
351+
</div>
352+
<div id="postamble" class="status">
353+
<p class="author">Author: 王月阳</p>
354+
<p class="date">Created: 2017-10-12 周四 10:36</p>
355+
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 24.5.1 (<a href="http://orgmode.org">Org</a> mode 8.2.10)</p>
356+
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
357+
</div>
358+
</body>
359+
</html>

0 commit comments

Comments
 (0)