併發編程(原理篇 上)

来源:http://www.cnblogs.com/houqian/archive/2016/07/26/5709063.html
-Advertisement-
Play Games

一、前言 七月的天氣分外炎熱,心中燥意難以撫平,決定梳理下之前落下的筆記。正好最近對JMM比較感興趣,就整理出了這篇文字。 二、序言 即使你的程式沒有顯示的創建任何線程,框架也可能為你創建了一些線程,這些線程調用的代碼必須是線程安全(thread safe)的。這一點給開發人員的設計和實現賦予了更重 ...


一、前言

七月的天氣分外炎熱,心中燥意難以撫平,決定梳理下之前落下的筆記。正好最近對JMM比較感興趣,就整理出了這篇文字。

二、序言

即使你的程式沒有顯示的創建任何線程,框架也可能為你創建了一些線程,這些線程調用的代碼必須是線程安全(thread safe)的。這一點給開發人員的設計和實現賦予了更重要的一分責任。

本文上下兩篇,主要通過圖文結合的方式描述瞭如下五個方面,希望有所幫助:

  • Java記憶體模型
  • 指令重排序
  • 順序一致性模型
  • volatile記憶體語義與實現
  • 鎖記憶體語義與實現

三、正文

1. Java記憶體模型

在併發編程中,需要處理兩個關鍵的問題:線程之間如何 通信 及線程之間如何 同步


通信

通信是指線程之間以何種機制來交換信息。在命令式編程語言中,線程之間的通信機制有兩種方法:共用記憶體消息傳遞

共用記憶體

這種併發模型中,線程之間通過寫-讀記憶體中的公共狀態來進行隱式通信。Java底層就是採用的這種方式。

消息傳遞

這種併發模型中,線程之間沒有公共狀態,線程之間必須通過發送消息來顯示進行通信。如:流行的Actor模型。

同步

Java線程之間的通信由Java記憶體模型控制(簡稱JMM),JMM決定一個線程對共用變數的寫入,何時對另一個線程可見。

JMM定義了線程和主記憶體之間的抽象關係:線程之間的共用變數存儲在主記憶體中,每個線程都有一個本地記憶體(Local Memory),本地記憶體中存儲了該線程讀/寫共用變數的副本。

由此可見,線程A與線程B要通信的話,必須經歷2個步驟。

a.線程A將本地記憶體中的副本刷寫到主記憶體中去。
b.線程B從主記憶體讀取已被A更新過的共用變數到B的本地記憶體

那麼,只要有其中一個環節沒有完成,線程間的可見性就得不到保障,造成數據的不准確。

2. 指令重排序

2.1 什麼是指令重排序?

在執行程式時,為了提高性能,編譯器和處理器常常會對指令做重排序。

2.2 指令重排序的條件

2.2.1 數據依賴性
如果兩個操作訪問統一個變數,且其中一個為寫操作,那麼這兩個操作之間就存在數據依賴性。

重排序在以上三種情況下不會觸發。

2.2.2 as-if-serial語義
as-if-serial語義的意思是:不管怎麼重排序,(單線程)程式的執行結果不能被改變。

我們通過一個計算圓面積的例子,說明這個問題:

可以看到,無論如何重排序,程式的結果是不變的,準確的。

以上,我們討論了單線程情況下重排序的影響。(好像與我們寫程式期望的目標一致: P),對於多線程程式,就未必如此了。


我們也是通過一個簡單的程式來說明該影響:

假設有兩個線程A和B,A先執行writer方法,然後B執行reader方法。
我們可以分析得到,這兩個方法內的代碼都不符合數據依賴性原則,因此都有可能被重排序。

重排序造成的執行路徑有很多種,我們這裡拿出其中的兩種來說明問題。


讀取到了未賦值的a變數

說明:int i = a * a;
這個操作可以分成兩個步驟,首先計算 a * a,接著賦值給變數i。

大家可以在腦中計算下這兩種情況下變數i的值。顯然,都不符合我們寫代碼期望的結果。我們初步認識到了,重排序對於多線程情況下的可能造成的負面影響。

3. 順序一致性模型

上面我們初步認識到了重排序可能對多線程的負面影響,那麼如何避免此種情況的發生呢?

我們下篇接著討論: D.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用asp:GridView顯示一個統計的表格 cs樣式: <style> table.gridview_m { border-collapse: collapse; border: solid 1px #93c2f1; width: 100%; font-size: 9pt; line-heigh ...
  • 從網上找到的一種加密代碼: 還有另一種SHA1加密,我用來做騰訊雲簽名: ...
  • 最近,項目中需要執行一個計劃任務,組長就讓我瞭解一下Quartz.net 這個組件,挺簡單的一個組件,實現起來特別的方便,靈活,值得推薦給大家一起學習一下這個小工具。以前我有的時候是使用定時器Timer,還有資料庫中的 計劃任務,後來發現這些真的太不好用了。下麵我介紹一下這個組件的使用步驟和註意事項 ...
  • 這個類庫是本人參考許多相關資料之後做出的C#矩陣運算類庫,因為C#的數值計算庫相對比較少,所以希望這個類庫能夠給大家帶來一些幫助。 源碼github網址:https://github.com/JoshuaHe2015/MatrixLibrary 功能介紹:(持續更新中) 1、矩陣的基本運算: 矩陣的 ...
  • 如過客戶端在向服務端介面進行請求,如果請求信息進行了加密處理,被第三方截取到請求包,雖然第三方無法解密獲取其中的數據,但是可以使用該請求包進行重覆的請求操作。如果服務端不進行防重放攻擊,就會參數伺服器壓力增大,數據紊亂的後果。而使用添加時間戳的方式可以解決這一問題。 ...
  • 強制類型轉換 package hello; import java.util.Scanner; public class Hello { public static void main(String[] args) { // TODO Auto-generated method stub Scann ...
  • curry翻譯為中文就是咖喱。意為使用curry可以讓代碼更有味道。 scala里的curry化可以把函數從接收多個參數轉換成接收多個參數列表。也就是說我們要編寫的函數不是只有一個參數列表,這個參數列表中有多個參數以逗號分隔;而是一個函數中有多個參數列表,每個參數列表中只有一個參數(當然,也可以有多... ...
  • 結合關係 一般自左向右 單目+- 和 賦值= 自右向左 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...