Java併發程式設計實戰筆記(一)
第一章
- 執行緒會共享程序範圍內的資源,例如記憶體控制代碼和檔案控制代碼,但每個執行緒都有各自的程式計數器(Program Counter)、棧以及區域性變數。
- 通過使用執行緒,可以將複雜並非同步的工作進一步分解為一組簡單並且同步的工作流,每個工作流在一個單獨的執行緒中執行,並在特定的同步位置進行互動。現有的一些框架可以實現上述目標,例如Servlet和RMI(Remote Mothod Invocation,遠端方法呼叫)。
- 安全性的含義是“永遠不發生糟糕的事情”,而活躍性則關注另一個目標,即“某件正確的事情最終會發生”。當某個操作無法繼續執行下去時,就會發生活躍性問題。在序列程式中,活躍性問題的形式之一就是無意中造成的無限迴圈。
- 與活躍性問題密切相關的是效能問題。活躍性意味著某件正確的事情最終會發送,但卻不夠好,因為我們希望正確的事情儘快傳送。
第二章
- 要編寫執行緒安全的程式碼,其核心在於要對狀態訪問操作進行管理,特別是對共享的(Shared)和可變的(Mutable)狀態的訪問。
- 如果當多個執行緒訪問同一個可變的狀態變數時沒有使用合適的同步,那麼程式就會出現錯誤,有3中方式可以修復這個問題:
i. 不線上程之間共享該變數。
ii. 將狀態變數修改為不可變的變數。
iii. 在訪問狀態變數時使用同步。 - 在編寫併發程式碼時,應始終遵循一個原則:首先使程式碼正確執行,然後才提高程式碼的執行速度。即便如此,最好也是當效能測試結果和應用需求告訴你必須提高效能,以及測量結果表明這種優化在實際環境中確實能帶來效能提升時,才進行優化。
- 線上程安全性的含義中,最核心的概念就是正確性,而正確性的含義是:某個類的行為與其規範完全一致。在良好的規範中通常會定義各種不變性條件(Invariant)來約束物件的狀態,以及定義各種後驗條件(Postcondition)來描述物件操作的結果。
- 當多個執行緒訪問某個類時,這個類始終都能表現出正確的行為,那麼就稱這個類是執行緒安全的。
- 無狀態物件一定是執行緒安全的。無狀態:既不包含任何域,也不包含任何對其他類中域的引用。
- 競態條件:在併發程式設計中,這種由於不恰當的執行時序而出現不正確的結果是一種非常重要的情況。
- 假定有兩個操作A和B,如果從執行A的執行緒來看,當另一個執行緒執行B時,要麼將B全部執行完,要麼完全不執行B,那麼A和B對彼此來說都是原子的。原子操作是指,對於訪問同一個狀態的所有操作(包括該操作本身)來說,這個操作是一個以原子方式執行的操作。
- 複合操作:包含了一組必須以原子方式執行的操作以確保執行緒安全性。
- 在實際情況中,應儘可能使用現有的執行緒安全物件(例如AtomicLong)來管理類的狀態。與非執行緒安全的物件相比,判斷執行緒安全物件的可能狀態及其狀態轉換情況要更為容易,從而也更容易驗證和維護執行緒安全性。
- 每個Java物件都可以用做一個實現同步的鎖,這些鎖被稱為內建鎖(Intrinsic Lock)或監視器鎖(Monitor Lock)。
- Java的內建鎖相當於一種互斥體(或互斥鎖),這意味著最多隻有一個執行緒能持有這個鎖。
- 內建鎖是可以重入的,因此如果某個執行緒試圖獲得一個已經有它自己持有的鎖,那麼這個請求就會成功。
- 對於可能被多個執行緒同時訪問的可變狀態變數,在訪問它時都需要持有同一個鎖,我們稱狀態變數是由這個鎖保護的。
- 每個共享的和可變的變數都應該只由一個鎖來保護,從而使維護人員知道是哪一個鎖。一種常見的加鎖約定是,將所有的可變狀態都封裝在物件內部,並通過物件的內建鎖對所有訪問可變狀態的程式碼路徑進行同步,使得在該物件上不會發生併發訪問。
- 在獲取與釋放鎖等操作上都需要一定的開銷,因此如果將同步程式碼塊分解的過細,那麼通常並不好,儘管這樣不會破壞原子性。
- 當執行時間較長的計算或者可能無法快速完成的操作時,一定不要持有鎖。
第三章
- Synchronized關鍵字不止能用於實現原子性或者確定“臨界區(Critical Section)”,還有另一個重要的方面:記憶體可見性(Memory Visibility)。
- 僅當volatile變數能簡化程式碼的實現以及對同步策略的驗證時,才應該使用它們。如果在驗證正確性時需要對可見性進行復雜的判斷,那麼就不要使用volatile變數。Volatile變數的正確使用方式包括:確保它們自身狀態的可見性,確保它們所引用物件的狀態的可見性,以及標識一些重要的程式生命週期事件的發生。
- 加鎖機制既可以確保可見性又可以確保原子性,而volatile變數只能確保可見性。
- 當且僅當滿足以下所有條件時,才應該使用volatile變數:
i. 對變數的寫入操作不依賴變數的當前值,或者你能確保只有單個執行緒更新變數的值。
ii. 該變數不會與其他狀態變數一起納入不變性條件中。
iii. 在訪問變數時不需要加鎖。 - 釋出(publish)一個物件的意思是指,是物件能夠在當前作用域之外的程式碼中使用。
- 逸出(Escape):當某個不應該釋出的物件被髮布時。
- 執行緒封閉:如果僅在單執行緒內訪問資料,就不需要同步。它是實現執行緒安全性的最簡單方式之一。
- Ad-hoc執行緒封閉:指維護執行緒封閉性的職責完全由程式實現來承擔。非常脆弱。程式中儘量少用。
- 棧封閉:它是執行緒封閉的一種特例,在棧封閉中,只能通過區域性變數才能訪問物件。區域性變數的固有屬性之一就是封閉在執行執行緒中。它們位於執行執行緒的棧中,其他執行緒無法訪問這個棧。
- ThreadLocal類:維護執行緒封閉性的一種更規範的方法是使用ThreadLocal類,這個類能使執行緒中的某個值與儲存值的物件關聯起來。ThreadLocal提供了get與set等訪問介面或方法,這些方法為每個使用該變數的執行緒都存有一份獨立的副本,因此get總是返回由當前執行執行緒在呼叫set時設定的最新值。
- ThreadLocal物件通常用於防止對可變的單例項變數或全域性變數進行共享。從概念上看,你可以將ThreadLocal視為包含了Map
相關推薦
Java併發程式設計實戰筆記(一)
第一章 執行緒會共享程序範圍內的資源,例如記憶體控制代碼和檔案控制代碼,但每個執行緒都有各自的程式計數器(Program Counter)、棧以及區域性變數。 通過使用執行緒,可以將複雜並非同步的工
Java併發程式設計讀書筆記(一)
前幾天整理電腦檔案的時候,突然發現了之前還在kindle儲存了關於併發程式設計的書,剛好自己在這方面挺薄弱的,故整理一波讀書筆記,繼續加強學習。 1.上下文切換 1.1 時間片分配演算法 時間片是CPU分配給各個執行緒的時間,CPU通過不停地切換執行緒執行,使各個執行緒彷彿是”同
java 併發程式設計學習筆記(一)之 併發基礎
併發基礎 併發小測試 java.util.concurrent.Semaphore 類 public class SemTest { /** * Se
java 併發程式設計學習筆記(一)之 基礎框架搭建和併發模擬工具,程式碼
基礎框架搭建和併發模擬工具,程式碼 (1)基礎框架搭建 (2)併發模擬 (3)CountDownLatch 通常用來 保證 幾個執行緒執行完成之後,再執行其他的程式碼 Semaphore
Java併發程式設計實踐筆記(一)
先如下程式碼:public class ListHelper<Integer> { public List<Integer> list = Collections .synchronizedList(new Array
Java併發程式設計實戰總結 (一)
# 前提 首先該場景是一個酒店開房的業務。為了朋友們閱讀簡單,我把業務都簡化了。 業務:開房後會新增一條賬單,新增一條房間排期記錄,房間排期主要是為了房間使用的時間不衝突。如:賬單A,使用房間1,使用時間段為2020-06-01 12:00 - 2020-06-02 12:00 ,那麼還需要使用房間1開房的時
java併發程式設計的藝術(一):併發程式設計的挑戰
併發程式設計的挑戰主要是在三個方面 上下文切換 死鎖 資源限制 下面就這三個方面進行分別分析遇到的挑戰以及如何應對。 1)上下文切換 1.1 什麼是上下文切換?多執行緒一定快麼? 想了解上下文切換,我們先來了解幾個概念。我們都知道在一塊CPU
併發程式設計學習:java併發程式設計的藝術(一)
一: 1.併發與並行:併發是多個執行緒(任務)共同爭奪一個cpu進行處理,並行是多個cpu各自處理對應的執行緒任務,現階段都只是併發而不是真正意義上的並行。 2.上下文切換: 即使單行處理器也支援多執行緒執行任務,cpu通過給每個執行緒分配cpu時
java 併發程式設計學習筆記(七)FutureTask, ForkJoin, BlockingQueue
(1)Future 、FutureTask public class FutureExample { static class MyTask implements Callable<String> { @Override pu
java併發程式設計的藝術(一)---鎖的基本屬性
這兩天在看《java併發程式設計的藝術》,記錄下看到的知識當做筆記吧! java中的synchronized鎖是儲存在物件頭中的,內容是mark word,長度根據計算機的位數來定32 or 64bit, 鎖一共有4種狀態,級別從低到高依次是:無鎖,偏向鎖,輕量級鎖,重量級鎖。鎖只能逐一升級,不能降級
Java 由淺入深GUI程式設計實戰練習(一)
專案簡介: 1.實現利用下拉選單的方式選擇傳送快捷語句; 2.實現對留言資訊內容的置頂處理以及至尾處理; 3.實現清屏處理或現實保留部分留言內容; 執行介面: 程式碼展示: import java.awt.BorderLayout; import java.awt.Button; imp
阿里Java開發手冊學習筆記(一)----程式設計規約
一、命名規範 不以下劃線(_)或美元符號($)開始/結尾。 不允許中英文混合使用,不允許直接使用中文。 類名使用UpperCamelCase風格;方法名、引數名、成員變數使用lowerCamelC
java程式設計規範筆記(一)
1. 命名風格 程式碼中的命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束 程式碼中的命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式 類名使用UpperCamelCase風格,必須遵從駝峰形式 方法名、引數名
java丨事件驅動程式設計學習筆記(一)
一、事件和事件源 事件:事件可以定義為程式發生了某些事情的訊號 源物件(源元件):能建立一個事件並觸發該事件的元件成為源物件 事件類的根類:java.util.EventObject 可以使用EventObject類中的例項方法getSource()獲得事件的源物件 如果一
Java高併發程式設計學習筆記(三):Java記憶體模型和執行緒安全
文章目錄 原子性 有序性 可見性 – 編譯器優化 – 硬體優化(如寫吸收,批操作) Java虛擬機器層面的可見性 Happen-Before規則(先行發生) 程式順序原則: volat
python高階程式設計讀書筆記(一)
python高階程式設計讀書筆記(一) python 高階程式設計讀書筆記,記錄一下基礎和高階用法 python2和python3相容處理 使用sys模組使程式python2和python3相容 import sysver=sys.version_info#(ma
Excel中VBA程式設計學習筆記(一)
1、註釋及編碼規則 註釋: 單引號:可以位於句子結尾或者單獨一行; Rem:單獨一行 編碼規則: 如果VB中的關鍵字是由多個英文字母組成,則系統自動將每個單詞的首字母轉換成大寫字母,其餘字母一律轉換成小寫字母。 對於使用者自定義的變數名、
JAVA類集框架筆記(一)
一、基本概念 : 1、所謂類集就是一個動態的物件陣列,是對一些實現好的資料結構和演算法進行包裝,方便使用。而且類集框架本身不受物件陣列的長度限制。 2、為了實現類集容易擴充套件和修