|
4 | 4 | <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> |
5 | 5 | <head> |
6 | 6 | <title>资源争用模型(泛多线程编程)</title> |
7 | | -<!-- 2017-09-19 周二 16:31 --> |
| 7 | +<!-- 2017-09-20 周三 17:21 --> |
8 | 8 | <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> |
9 | 9 | <meta name="generator" content="Org-mode" /> |
10 | 10 | <meta name="author" content="王月阳" /> |
@@ -351,51 +351,132 @@ <h2 id="sec-4"><span class="section-number-2">4</span> 资源争用模型</h2> |
351 | 351 | <div class="outline-text-2" id="text-4"> |
352 | 352 | </div><div id="outline-container-sec-4-1" class="outline-3"> |
353 | 353 | <h3 id="sec-4-1"><span class="section-number-3">4.1</span> 资源争用模型的含义</h3> |
| 354 | +<div class="outline-text-3" id="text-4-1"> |
| 355 | +<p> |
| 356 | +资源争用,顾名思义就是不同的使用者对共享的资源进行原子性使用。下面我们从日常生活中举个例子来说明一下什么是资源争用。 |
| 357 | +</p> |
| 358 | +</div> |
354 | 359 | </div> |
355 | | - |
356 | 360 | <div id="outline-container-sec-4-2" class="outline-3"> |
357 | 361 | <h3 id="sec-4-2"><span class="section-number-3">4.2</span> 例子</h3> |
358 | | -</div> |
| 362 | +<div class="outline-text-3" id="text-4-2"> |
| 363 | +<p> |
| 364 | +举个常见的高速路出口的例子。在这个例子中,不同的车辆就是不同的使用者,高速路出口就是共享的资源。当多辆车同时到达高速 |
| 365 | +路出口的时候,一个出口同一个时间点只能允许一辆车通行,这可怎么办呢?现实生活中是什么样的呢,所有车辆排队依次通过出口。 |
| 366 | +当车流量特别大的时候,排队的车辆就会很多,又怎么办,增开高速路出口,把车辆分散到不同的出口。所以在本例中,保证业务正 |
| 367 | +常进行的两个点分别是排队和增加资源,当然是基于操作是原子的前提下。 |
| 368 | +</p> |
| 369 | + |
| 370 | +<p> |
| 371 | +再举个饭店里顾客点菜厨师炒菜的例子,在这个例子中,厨师就是共享的资源,顾客就是资源争用者。那么正常生活中,是怎么保证 |
| 372 | +菜被正常的做出来的呢?客户A点了一个菜之后,厨师开始炒菜;然后另一个人B又点了10个菜,这10个菜都由服务员通知厨师炒了。然后厨师 |
| 373 | +就会按照服务员给的菜单的顺序一个一个炒菜。在本例中,我们默认了一个前提,就是炒菜是一个一个炒的,这是一个原子的操 |
| 374 | +作,不可分割。不然厨师把炒这个菜的盐放到了另一个菜的锅里,就这跪了。在本例中,我们还有一个大家习以为常的点,就是厨师 |
| 375 | +会自动的一个一个的炒菜,厨师会人工判断先炒那个菜后炒那个菜,这是不是就相当于给业务线程排了个队呢?除去排队,还有什么 |
| 376 | +方法能减少争用呢?套路来了,增加资源啊。。。 |
| 377 | +</p> |
359 | 378 |
|
| 379 | +<p> |
| 380 | +所以,在资源争用模型中,要么排队,要么加资源。 |
| 381 | +</p> |
| 382 | +</div> |
| 383 | +</div> |
360 | 384 | <div id="outline-container-sec-4-3" class="outline-3"> |
361 | 385 | <h3 id="sec-4-3"><span class="section-number-3">4.3</span> 从争的角度解决问题(排队模型)</h3> |
362 | 386 | <div class="outline-text-3" id="text-4-3"> |
363 | 387 | </div><div id="outline-container-sec-4-3-1" class="outline-4"> |
364 | 388 | <h4 id="sec-4-3-1"><span class="section-number-4">4.3.1</span> 排队的本质就是有序</h4> |
| 389 | +<div class="outline-text-4" id="text-4-3-1"> |
| 390 | +<p> |
| 391 | +从上一节的例子可以看出,解决争用一个常见的方式就是让操作有序。这个模型我们可以叫它排队模型。通过各种操作的排队,实现 |
| 392 | +操作有序,进而实现对资源的原子操作,保证资源的安全。 |
| 393 | +</p> |
| 394 | +</div> |
365 | 395 | </div> |
366 | 396 | <div id="outline-container-sec-4-3-2" class="outline-4"> |
367 | 397 | <h4 id="sec-4-3-2"><span class="section-number-4">4.3.2</span> 排队的实现</h4> |
| 398 | +<div class="outline-text-4" id="text-4-3-2"> |
| 399 | +<p> |
| 400 | +那么,排队模型怎么实现呢?就说高速路出口的例子,两车司机同时想跟在一个车后面的时候,大概是通过眼神交流,协商好,谁在 |
| 401 | +前面谁在后面 。饭店那个例子中,做菜的先后顺序,应该是按照点菜的顺序,先来后到。这其实就是实现排队的两种方法。其一, |
| 402 | +就是大家协商;其二就是操作在到达争用之前,本身就是有序的。 |
| 403 | +</p> |
| 404 | + |
| 405 | +<p> |
| 406 | +对应在Java中,协商是怎么实现的呢?线程不可能像人一样有自主思维意识,知道礼让排队。那么线程能怎么判断能不能操作资源呢? |
| 407 | +那么,我们可以从资源的角度来看,当资源已经被占用的时候,新来的线程是不用操作资源的,只能等待。资源没有被其他线程占用, |
| 408 | +也就是空闲的时候,才能被线程操作。那么线程要获取资源的操作权限的时候,可以先判断资源状态,空闲才能使用资源,使用过程 |
| 409 | +说要将资源的状态设置为被占用,使用完成之后将资源状态设置为空闲。 |
| 410 | +</p> |
| 411 | + |
| 412 | +<p> |
| 413 | +实际使用过程中,我们不可能说为每个共享的资源去设置一个状态字段,因为这与业务本身是无关的,应该被抽象出来作为一个通用 |
| 414 | +的逻辑。怎么抽象呢,其实我们就需要一个状态字段,标明对应的资源是被占用还是空闲状态,这个字段可以以任何形式存在,没必 |
| 415 | +要放在资源对象里面。 |
| 416 | +</p> |
| 417 | + |
| 418 | +<p> |
| 419 | +前面说的是协商实现排队的方式。还有一种方式就是让自然争用者自带顺序,比如按先来后到,比如到达资源争用之前,每个争用者 |
| 420 | +分配一个序列号,按序列号使用资源。 |
| 421 | +</p> |
| 422 | +</div> |
368 | 423 | </div> |
369 | 424 | </div> |
370 | | - |
371 | 425 | <div id="outline-container-sec-4-4" class="outline-3"> |
372 | 426 | <h3 id="sec-4-4"><span class="section-number-3">4.4</span> 从资源的角度解决问题</h3> |
373 | 427 | <div class="outline-text-3" id="text-4-4"> |
374 | | -</div><div id="outline-container-sec-4-4-1" class="outline-4"> |
| 428 | +<p> |
| 429 | +从资源的角度来解决资源争用的问题,就是提供足够多的资源,让使用者不去争。不争的还有一种方式就是资源是可被复用的,这相 |
| 430 | +当于有无限多份资源,是足够多资源的一种特例。 |
| 431 | +</p> |
| 432 | +</div> |
| 433 | +<div id="outline-container-sec-4-4-1" class="outline-4"> |
375 | 434 | <h4 id="sec-4-4-1"><span class="section-number-4">4.4.1</span> 不共享资源 CopyOnWrite</h4> |
| 435 | +<div class="outline-text-4" id="text-4-4-1"> |
| 436 | +<p> |
| 437 | +不共享资源的一种实现方式是来一个争用者就创建一份新在资源给争用者使用,这样就不会跟其他争用者产生竞争关系。 |
| 438 | +</p> |
| 439 | +</div> |
376 | 440 | </div> |
377 | 441 | <div id="outline-container-sec-4-4-2" class="outline-4"> |
378 | 442 | <h4 id="sec-4-4-2"><span class="section-number-4">4.4.2</span> 资源不可变 ImmutableData</h4> |
| 443 | +<div class="outline-text-4" id="text-4-4-2"> |
| 444 | +<p> |
| 445 | +这是不共享的一种特例,相当于有无限多份资源,每个争用者可以自由使用。 |
| 446 | +</p> |
| 447 | +</div> |
379 | 448 | </div> |
380 | 449 | </div> |
381 | | - |
382 | 450 | <div id="outline-container-sec-4-5" class="outline-3"> |
383 | 451 | <h3 id="sec-4-5"><span class="section-number-3">4.5</span> 更细的粒度</h3> |
384 | 452 | <div class="outline-text-3" id="text-4-5"> |
385 | 453 | </div><div id="outline-container-sec-4-5-1" class="outline-4"> |
386 | 454 | <h4 id="sec-4-5-1"><span class="section-number-4">4.5.1</span> 共享锁与排他锁</h4> |
| 455 | +<div class="outline-text-4" id="text-4-5-1"> |
| 456 | +<p> |
| 457 | +对资源的使用有两种情况,一是使用会修改资源,二是使用不修改资源。对于只有不修改资源的这种使用场景,就相当于资源不可变。 |
| 458 | +但对于有修改资源操作的场景,就要排队了。也就是说修改操作是互斥的,修改操作和不修改操作是互斥的。所以因为怼资源操作的 |
| 459 | +不同,所以资源占用对应的状态也不相同, |
| 460 | +</p> |
| 461 | +</div> |
387 | 462 | </div> |
388 | 463 | <div id="outline-container-sec-4-5-2" class="outline-4"> |
389 | 464 | <h4 id="sec-4-5-2"><span class="section-number-4">4.5.2</span> MVCC</h4> |
| 465 | +<div class="outline-text-4" id="text-4-5-2"> |
| 466 | +<p> |
| 467 | +MVCC是一种结合了资源与排队两个方面的方法实现的争用模型,首先,资源每个版本都一个唯一的序列号,不同版本的序列号是有顺 |
| 468 | +序的,争用者获取资源的操作之后,得到资源版本号,比如99;当要修改资源的时候,会带着序列号来操作,这样就实现了排队。而 |
| 469 | +对于不修改资源的操作来说,可以正常获取资源,没有争用。 |
| 470 | +</p> |
| 471 | +</div> |
390 | 472 | </div> |
391 | 473 | </div> |
392 | 474 | </div> |
393 | | - |
394 | 475 | <div id="outline-container-sec-5" class="outline-2"> |
395 | 476 | <h2 id="sec-5"><span class="section-number-2">5</span> Java内存模型与资源争用</h2> |
396 | 477 | <div class="outline-text-2" id="text-5"> |
397 | 478 | <p> |
398 | | -用一个状态位标识资源状态:可用不可用,可写不可写,可读不可读 |
| 479 | +我们前面总结的,可以用一个状态位标识资源状态:可用不可用,可写不可写,可读不可读。通过这个状态值实现对资源的安全操作。 |
399 | 480 | </p> |
400 | 481 | </div> |
401 | 482 | <div id="outline-container-sec-5-1" class="outline-3"> |
@@ -488,7 +569,7 @@ <h3 id="sec-7-2"><span class="section-number-3">7.2</span> Zookeeper一主多从 |
488 | 569 | </div> |
489 | 570 | <div id="postamble" class="status"> |
490 | 571 | <p class="author">Author: 王月阳</p> |
491 | | -<p class="date">Created: 2017-09-19 周二 16:31</p> |
| 572 | +<p class="date">Created: 2017-09-20 周三 17:21</p> |
492 | 573 | <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> |
493 | 574 | <p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p> |
494 | 575 | </div> |
|
0 commit comments