閱界資訊

併發編程(零):併發問題與討論範圍

閱閱界編輯部1閱讀7分鐘

《併發編程(零):併發問題與討論範圍》這篇在博客園熱度很高,講的正是大家天天碰到的事。下面幫你把要點捋出來,結尾有能直接抄的結論。

目錄 1. 先明確討論範圍 2. 從一個共享變量開始 3. 兩種主要的協作模型 3.1 Shared Memory:通過同步保護共享狀態 3.2 Message Passing:通過消息進行協作 4. 爲什麼這些代碼能夠正確工作? 5. 語言需要定義併發語義 6. 爲什麼還要繼續下鑽到硬件? 7. 下一篇:先談硬件 1. 先明確討論範圍 這個系列只討論: 單機、單進程內部的併發。 也就是說,我們關注的是同一個進程中的多個執行單元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不討論跨進程通信、分佈式系統和網絡通信。 2. 從一個共享變量開始 假設進程中有一個變量: [代碼示例略] 現在有兩個執行單元: [代碼示例略] 如果 A 和 B 各執行一次,最終結果是否一定是: [代碼示例略] 答案是不一定。

目錄 1. 先明確討論範圍 2. 從一個共享變量開始 3. 兩種主要的協作模型 3.1 Shared Memory:通過同步保護共享狀態 3.2 Message Passing:通過消息進行協作 4. 爲什麼這些代碼能夠正確工作? 5. 語言需要定義併發語義 6. 爲什麼還要繼續下鑽到硬件? 7. 下一篇:先談硬件 1. 先明確討論範圍 這個系列只討論: 單機、單進程內部的併發。 也就是說,我們關注的是同一個進程中的多個執行單元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不討論跨進程通信、分佈式系統和網絡通信。 2. 從一個共享變量開始 假設進程中有一個變量: [代碼示例略] 現在有兩個執行單元: [代碼示例略] 如果 A 和 B 各執行一次,最終結果是否一定是: [代碼示例略] 答案是不一定。 因爲 count++ 可以從邏輯上拆成三個步驟: [代碼示例略] 於是可能出現: [代碼示例略] 最終: [代碼示例略] 兩個線程都完成了一次 +1 ,但因爲它們讀取到了相同的舊值 0 ,最終兩次計算結果都只是 1 ,其中一次更新被覆蓋了。

目錄 1. 先明確討論範圍 2. 從一個共享變量開始 3. 兩種主要的協作模型 3.1 Shared Memory:通過同步保護共享狀態 3.2 Message Passing:通過消息進行協作 4. 爲什麼這些代碼能夠正確工作? 5. 語言需要定義併發語義 6. 爲什麼還要繼續下鑽到硬件? 7. 下一篇:先談硬件 1. 先明確討論範圍 這個系列只討論: 單機、單進程內部的併發。 也就是說,我們關注的是同一個進程中的多個執行單元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不討論跨進程通信、分佈式系統和網絡通信。 2. 從一個共享變量開始 假設進程中有一個變量: [代碼示例略] 現在有兩個執行單元: [代碼示例略] 如果 A 和 B 各執行一次,最終結果是否一定是: [代碼示例略] 答案是不一定。 因爲 count++ 可以從邏輯上拆成三個步驟: [代碼示例略] 於是可能出現: [代碼示例略] 最終: [代碼示例略] 兩個線程都完成了一次 +1 ,但因爲它們讀取到了相同的舊值 0 ,最終兩次計算結果都只是 1 ,其中一次更新被覆蓋了。 問題的關鍵在於兩個Thread同時修改了 counter ,也就是 多個執行單元同時訪問並修改了同一份狀態。

目錄 1. 先明確討論範圍 2. 從一個共享變量開始 3. 兩種主要的協作模型 3.1 Shared Memory:通過同步保護共享狀態 3.2 Message Passing:通過消息進行協作 4. 爲什麼這些代碼能夠正確工作? 5. 語言需要定義併發語義 6. 爲什麼還要繼續下鑽到硬件? 7. 下一篇:先談硬件 1. 先明確討論範圍 這個系列只討論: 單機、單進程內部的併發。 也就是說,我們關注的是同一個進程中的多個執行單元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不討論跨進程通信、分佈式系統和網絡通信。 2. 從一個共享變量開始 假設進程中有一個變量: [代碼示例略] 現在有兩個執行單元: [代碼示例略] 如果 A 和 B 各執行一次,最終結果是否一定是: [代碼示例略] 答案是不一定。 因爲 count++ 可以從邏輯上拆成三個步驟: [代碼示例略] 於是可能出現: [代碼示例略] 最終: [代碼示例略] 兩個線程都完成了一次 +1 ,但因爲它們讀取到了相同的舊值 0 ,最終兩次計算結果都只是 1 ,其中一次更新被覆蓋了。 問題的關鍵在於兩個Thread同時修改了 counter ,也就是 多個執行單元同時訪問並修改了同一份狀態。 在單機、單進程範圍內,當多個執行單元需要共享數據時,主要通過兩種模型協作: Shared Memory / Shared State :多個執行單元直接訪問同一份狀態; Message Passing :執行單元之間通過消息交換信息。

目錄 1. 先明確討論範圍 2. 從一個共享變量開始 3. 兩種主要的協作模型 3.1 Shared Memory:通過同步保護共享狀態 3.2 Message Passing:通過消息進行協作 4. 爲什麼這些代碼能夠正確工作? 5. 語言需要定義併發語義 6. 爲什麼還要繼續下鑽到硬件? 7. 下一篇:先談硬件 1. 先明確討論範圍 這個系列只討論: 單機、單進程內部的併發。 也就是說,我們關注的是同一個進程中的多個執行單元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不討論跨進程通信、分佈式系統和網絡通信。 2. 從一個共享變量開始 假設進程中有一個變量: [代碼示例略] 現在有兩個執行單元: [代碼示例略] 如果 A 和 B 各執行一次,最終結果是否一定是: [代碼示例略] 答案是不一定。 因爲 count++ 可以從邏輯上拆成三個步驟: [代碼示例略] 於是可能出現: [代碼示例略] 最終: [代碼示例略] 兩個線程都完成了一次 +1 ,但因爲它們讀取到了相同的舊值 0 ,最終兩次計算結果都只是 1 ,其中一次更新被覆蓋了。 問題的關鍵在於兩個Thread同時修改了 counter ,也就是 多個執行單元同時訪問並修改了同一份狀態。 在單機、單進程範圍內,當多個執行單元需要共享數據時,主要通過兩種模型協作: Shared Memory / Shared State :多個執行單元直接訪問同一份狀態; Message Passing :執行單元之間通過消息交換信息。 下面仍然以 count++ 爲例,看這兩種模型分別如何處理前面的併發問題。

行動建議:收藏這篇,下次碰到同類問題先翻出來對照做一遍。好經驗的價值,在於用起來。你最近被這類問題卡過嗎? 來源|博客園《併發編程(零):併發問題與討論範圍》,https://www.cnblogs.com/ThinkerQAQ/p/22954074.html

程式員技術場技术后端

評論(0)

暫無評論,來搶第一條。