天天看點

Oracle官方并發教程之活躍度

一個并發應用程式能及時執行的能力稱為活躍性。本節将介紹最常見的活躍性問題:死鎖(deadlock),以及另外兩個活躍性問題:饑餓(starvation)和活鎖(livelock)。

<a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html">原文位址</a>

死鎖描述了這樣一種情景,兩個或多個線程永久阻塞,互相等待對方釋放資源。下面是一個例子。

alphone和gaston是朋友,都很講究禮節。禮節有一個嚴格的規矩,當你向一個朋友鞠躬時,你必須保持鞠躬的姿勢,直到你的朋友有機會回鞠給你。不幸的是,這個規矩沒有算上兩個朋友互相同時鞠躬的可能。

下面的應用例子,deadlock,模拟了這個可能性。

<code>01</code>

<code>   </code><code>static</code> <code>class</code> <code>friend {</code>

<code>02</code>

<code>        </code><code>private</code> <code>final</code> <code>string name;</code>

<code>03</code>

<code>        </code><code>public</code> <code>friend(string name) {</code>

<code>04</code>

<code>            </code><code>this</code><code>.name = name;</code>

<code>05</code>

<code>        </code><code>}</code>

<code>06</code>

<code>        </code><code>public</code> <code>string getname() {</code>

<code>07</code>

<code>            </code><code>return</code> <code>this</code><code>.name;</code>

<code>08</code>

<code>09</code>

<code>        </code><code>public</code> <code>synchronized</code> <code>void</code> <code>bow(friend bower) {</code>

<code>10</code>

<code>            </code><code>system.out.format(</code><code>"%s: %s"</code>

<code>11</code>

<code>                </code><code>+ </code><code>"  has bowed to me!%n"</code><code>,</code>

<code>12</code>

<code>                </code><code>this</code><code>.name, bower.getname());</code>

<code>13</code>

<code>            </code><code>bower.bowback(</code><code>this</code><code>);</code>

<code>14</code>

<code>15</code>

<code>        </code><code>public</code> <code>synchronized</code> <code>void</code> <code>bowback(friend bower) {</code>

<code>16</code>

<code>17</code>

<code>                </code><code>+ </code><code>" has bowed back to me!%n"</code><code>,</code>

<code>18</code>

<code>19</code>

<code>20</code>

<code>    </code><code>}</code>

<code>21</code>

<code>22</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>

<code>23</code>

<code>        </code><code>final</code> <code>friend alphonse =</code>

<code>24</code>

<code>            </code><code>new</code> <code>friend(</code><code>"alphonse"</code><code>);</code>

<code>25</code>

<code>        </code><code>final</code> <code>friend gaston =</code>

<code>26</code>

<code>            </code><code>new</code> <code>friend(</code><code>"gaston"</code><code>);</code>

<code>27</code>

<code>        </code><code>new</code> <code>thread(</code><code>new</code> <code>runnable() {</code>

<code>28</code>

<code>            </code><code>public</code> <code>void</code> <code>run() { alphonse.bow(gaston); }</code>

<code>29</code>

<code>        </code><code>}).start();</code>

<code>30</code>

<code>31</code>

<code>            </code><code>public</code> <code>void</code> <code>run() { gaston.bow(alphonse); }</code>

<code>32</code>

<code>33</code>

<code>34</code>

<code>}</code>

當deadlock運作後,兩個線程極有可能阻塞,當它們嘗試調用bowback方法時。沒有哪個阻塞會結束,因為每個線程都在等待另一個線程退出bow方法。

<a href="http://docs.oracle.com/javase/tutorial/essential/concurrency/starvelive.html">原文位址</a>

饑餓和活鎖并不如死鎖一般普遍,但它仍然是每個并發程式設計者可能會遇到的問題。

饑餓是指當一個線程不能正常的通路共享資源并且不能正常執行的情況。這通常在共享資源被其他“貪心”的線程長期時發生。舉個例子,假設一個對象提供了一個同步方法,這個方法通常需要執行很長一段時間才傳回。如果一個線程經常調用這個方法,那麼其他需要同步的通路這個對象的線程就經常會被阻塞。

一個線程通常會有會響應其他線程的活動。如果其他線程也會響應另一個線程的活動,那麼就有可能發生活鎖。同死鎖一樣,發生活鎖的線程無法繼續執行。然而線程并沒有阻塞——他們在忙于響應對方無法恢複工作。這就相當于兩個在走廊相遇的人:alphonse向他自己的左邊靠想讓gaston過去,而gaston向他的右邊靠想讓alphonse過去。可見他們阻塞了對方。alphonse向他的右邊靠,而gaston向他的左邊靠,他們還是阻塞了對方。