《Java併發編程實踐——第一章(介紹)、第二章(線程安全)》

介紹##

1.1 併發的簡短歷史

相同的關注點(資源利用,公平和方便) 不僅促進了進程的發展,也促進了線程的發展、
線程允許程序控制流的多重分支同時存在於一個進程。它們共享進程範圍內的資源,比如內存和文件句柄,但是線程有自己的程序計數器、棧、和本地變量。

1.2 線程的優點

提高性能,降低程序複雜度。在服務器應用中,提高資源利用率和吞吐量。

1.3 線程的風險

1.3.1 安全危險

在這裏插入圖片描述
競爭條件:當被多線程調用時,getNext是否能返回不重複的值。
因爲線程共享相同的內存地址空間,且併發地運行,它可能訪問或修改其他線程正在使用的變量。

1.3 線程無處不在

定時器:Timer訪問的數據必須是線程安全的。
Servlet:Servlet可能會訪問共享的對象(Session等),必須是線程安全
遠程方法調用:RMI使你能夠調用在另外一個JVM上運行的對象的方法。

線程安全##

編寫線程安全的代碼,本質上就是對狀態的方法,而且通常都是共享的、可變的狀態。

狀態:一個對象的狀態就是它的數據,存儲在狀態變量,比如實例或靜態域。
包含了任何會對它外部可見行爲產生影響的數據。
共享:指一個變量可以被多個線程訪問。
可變:指變量在其生命週期內可以改變。

2.1 什麼是線程安全性

在這裏插入圖片描述

2.1.1 無狀態的servlet

無狀態對象永遠是線程安全的。

不包含域,也沒有引用其他類的域

2.2 原子性

原子性:不能作爲單獨的、不可分割的操作。
count++:包含了三次操作,讀-改-寫。

2.2.1 競爭條件

檢查再運行:使用潛在的過期觀察值來做決策或執行計算。

2.2.2 惰性初始化中的競爭條件

檢查再運行的常見用法是惰性初始化:
在這裏插入圖片描述
競爭條件並不總是失敗的,還需要某些特殊的分時。

2.2.3 複合操作

檢查再運行和讀-改-寫的操作看成複合操作:操作必須原子地執行。
可以使用已有的線程安全類:aromic包。

2.3 鎖

爲了保護狀態的一致性,要在單一的原子操作中更新相互關聯的狀態變量。

2.3.1 內部鎖

內部鎖:每個Java對象都可以隱式地扮演一個用於同步的鎖的角色。
在這裏插入圖片描述

synchronized放的鎖就是該方法所在的對象本身。

2.3.2 重進入

當一個線程請求其他線程已經佔有的鎖時,請求線程將被阻塞。
然後內部鎖是可重進入的。
JVM會被每個鎖關聯一個請求計數,計數爲0表示未被佔有。
在這裏插入圖片描述
子類覆寫了父類的synchronized類型的方法,如果沒有可重入鎖,看上去像死鎖。

2.4 用鎖來保護狀態

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2.5 活躍度和性能

在這裏插入圖片描述

service方法聲明爲synchronized,因此每次只能有一個線程執行它。這違背了Servlet的初衷:同時處理多個請求。
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章