concurrency 并行編程

Goroutine

go語言的魅力所在,高并發。

線程是操作系統調度的一種執行路徑,用于在處理器執行我們在函數中編寫的代碼。一個進程從一個線程開始,即主線程,當該線程終止時,進程終止。這是因為主線程是應用程序的原點。然后,主線程可以依次啟動更多的線程,而這些線程可以啟動更多的線程。

并發不是并行。并行是指兩個或多個線程同時在不同的處理器執行代碼。如果將運行時配置為使用多個邏輯處理器,則調度程序將在這些邏輯處理器之間分配 goroutine,這將導致 goroutine 在不同的操作系統線程上運行。但是,要獲得真正的并行性,您需要在具有多個物理處理器的計算機上運行程序。否則,goroutine 將針對單個物理處理器并發運行,即使 Go 運行時使用多個邏輯處理器。

注意:① 空的 select{} 會永遠進行 阻塞

② 如果當前的goroutine要執行但是需要等待另一個goroutine執行完畢才行,這時候就要把另一個goroutine的事情拿來自己做。

③ 使用goroutine考慮兩個問題,一是它什么時候結束,二是你有沒有一個方法讓它結束

這里展示一個較好例子:

Memory model

go 的內存模型,個人總結:只要是多線程就不要覺得自己太聰明,使用”鎖",確保操作事物的原子性,因為多線程之間的調度過程中,cpu,線程為了最大限度的性能,有可能改變不同線程之間關于整體事物的邏輯執行順序,導致結果出現不可測性。指針copy的方法,指針是一個原子性,但是并不滿足 single machine. 當然如果你只是單線程,那么這些憂慮不用考慮

為了說明讀和寫的必要條件,我們定義了先行發生(Happens Before)。如果事件 e1 發生在 e2 前,我們可以說 e2 發生在 e1 后。如果 e1不發生在 e2 前也不發生在 e2 后,我們就說 e1 和 e2 是并發的。
在單一的獨立的 goroutine 中先行發生的順序即是程序中表達的順序。

  • 當下面條件滿足時,對變量 v 的讀操作 r 是被允許看到對 v 的寫操作 w 的:
    • r 不先行發生于 w
    • 在 w 后 r 前沒有對 v 的其他寫操作
  • 為了保證對變量 v 的讀操作 r 看到對 v 的寫操作 w,要確保 w 是 r 允許看到的唯一寫操作。即當下面條件滿足時,r 被保證看到 w:
    • w 先行發生于 r
    • 其他對共享變量 v 的寫操作要么在 w 前,要么在 r 后。


這一對條件比前面的條件更嚴格,需要沒有其他寫操作與 w 或 r 并發發生。

Package sync

data race : 線程競爭,在線程模型中Go 沒有顯式地使用鎖來協調對共享數據的訪問,而是鼓勵使用 chan 在 goroutine 之間傳遞對數據的引用。這種方法確保在給定的時間只有一個 goroutine 可以訪問數據。

go buid -race go test -race

i++是原子性操作嗎? 不是,i++的底層是三行代碼,并不是原子性。

Copy-On-Write 思路在微服務降級或者 local cache 場景中經常使用。寫時復制指的是,寫操作時候復制全量老數據到一個新的對象中,攜帶上本次新寫的數據,之后利用原子替換(atomic.Value),更新調用者的變量。來完成無鎖訪問共享數據。這也是 Redis 進行寫操作來更改數據的一種方法。

Mutex

  • go的幾種 Mutex 鎖的實現:
    • Barging. 這種模式是為了提高吞吐量,當鎖被釋放時,它會喚醒第一個等待者,然后把鎖給第一個等待者或者給第一個請求鎖的人。
    • Handsoff. 當鎖釋放時候,鎖會一直持有直到第一個等待者準備好獲取鎖。它降低了吞吐量,因為鎖被持有,即使另一個 goroutine 準備獲取它。(一個互斥鎖的 handsoff 會完美地平衡兩個goroutine 之間的鎖分配,但是會降低性能,因為它會迫使第一個 goroutine 等待鎖。)
    • Spinning. 自旋在等待隊列為空或者應用程序重度使用鎖時效果不錯。parking 和 unparking goroutines 有不低的性能成本開銷,相比自旋來說要慢得多。

errgroup

實際生活中我們的errgroup使用的更多一些,用幾個gooroutine 去進行分布處理業務,然后通過sync進行控制管理各個分支,把最后的數據再集合起來。 sync.waitGroup()

Chan

各個goroutine通過chan管道來進行實時通信。

channels 是一種類型安全的消息隊列,充當兩個 goroutine 之間的管道,將通過它同步的進行任意資源的交換。chan 控制 goroutines 交互的能力從而創建了 Go 同步機制。當創建的 chan 沒有容量時,稱為無緩沖通道。反過來,使用容量創建的 chan 稱為緩沖通道。

無緩沖chan

ch := make(chan struct{})
無緩沖 chan 沒有容量,因此進行任何交換前需要兩個 goroutine 同時準備好。當 goroutine 試圖將一個資源發送到一個無緩沖的通道并且沒有goroutine 等待接收該資源時,該通道將鎖住發送 goroutine 并使其等待。當 goroutine 嘗試從無緩沖通道接收,并且沒有 goroutine 等待發送資源時,該通道將鎖住接收 goroutine 并使其等待。
意思就是雙方都得準備好才能進行下去 , 無緩沖信道的本質是保證同步。

  • Receive 先于 Send 發生。
  • 好處: 100% 保證能收到。
  • 代價: 延遲時間未知。

有緩沖的chan

buffered channel 具有容量,因此其行為可能有點不同。當 goroutine 試圖將資源發送到緩沖通道,而該通道已滿時,該通道將鎖住 goroutine并使其等待緩沖區可用。如果通道中有空間,發送可以立即進行,goroutine 可以繼續。當goroutine 試圖從緩沖通道接收數據,而緩沖通道為空時,該通道將鎖住 goroutine 并使其等待資源被發送。

  • Send 先于 Receive 發生。
  • 好處: 延遲更小。
  • 代價: 不保證數據到達,越大的 buffer,越小的保障到達。buffer = 1 時,給你延遲一個消息的保障。

Context

context 的使用因該是貫穿全過程,而不是被把它放到一個對象結構體中去使用

context.WithValue() : 用于創建一個context對象

context.WithValue 方法允許上下文攜帶請求范圍的數據。這些數據必須是安全的,以便多個 goroutine 同時使用。這里的數據,更多是面向請求的元數據,不應該作為函數的可選參數來使用(比如 context 里面掛了一個sql.Tx 對象,傳遞到 data 層使用),因為元數據相對函數參數更加是隱含的,面向請求的。而參數是更加顯示的。

同一個 context 對象可以傳遞給在不同 goroutine 中運行的函數;上下文對于多個 goroutine 同時使用是安全的。對于值類型最容易犯錯的地方,在于 context value 應該是 immutable 的,每次重新賦值應該是新的 context,即: context.WithValue(ctx, oldvalue)

比如 染色,API 重要性,Trace

注意選擇使用 copy-on-write 的思路,解決跨多個 goroutine 使用數據、修改數據的場景。

COW: 從 ctx1 中獲取 map1(可以理解為 v1 版本的 map 數據)。構建一個新的 map 對象 map2,復制所有 map1 數據,同時追加新的數據 “k2”: “v2” 鍵值對,使用 context.WithValue 創建新的 ctx2,ctx2 會傳遞到其他的 goroutine 中。這樣各自讀取的副本都是自己的數據,寫行為追加的數據,在 ctx2 中也能完整讀取到,同時也不會污染 ctx1 中的數據。

COW就是 copy-on-write

當一個 context 被取消時,從它派生的所有 context 也將被取消。WithCancel(ctx) 參數 ctx 認為是 parent ctx,在內部會進行一個傳播關系鏈的關聯。Done() 返回 一個 chan,當我們取消某個parent context, 實際上上會遞歸層層 cancel 掉自己的 child context 的 done chan 從而讓整個調用鏈中所有監聽 cancel 的 goroutine 退出。

如果要實現一個超時控制,通過上面的 context 的 parent/child 機制,其實我們只需要啟動一個定時器,然后在超時的時候,直接將當前的 context 給 cancel 掉,就可以實現監聽在當前和下層的額 context.Done() 的 goroutine 的退出。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/16030.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/16030.shtml
英文地址,請注明出處:http://en.pswp.cn/web/16030.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

紅黑樹封裝map和set

紅黑樹源代碼 我們將由下列的KV模型紅黑樹來模擬封裝STL庫中的map和set 注意&#xff1a;為了實現封裝map和set&#xff0c;我們需要對下列源碼進行優化。 #pragma once #include<iostream> using namespace std; //枚舉類型的顏色分類 enum Colour {RED,BLACK };//定…

【Python爬蟲】圖片驗證碼的處理

什么是圖片驗證碼&#xff1f; 驗證碼&#xff08;CAPTCHA&#xff09;是&#xff02;Completely Automated Public Turing test to tell Computers and HumansApart”&#xff08;全自動區分計算機和人類的圖靈測試&#xff09;的縮寫&#xff0c;是一種區分用戶是計算機還是人…

Markdown魔法手冊:解鎖高效寫作的新技能

邊使用邊更新0.0... 文章目錄 一、如何在Markdown中插入表情&#xff1f;二、文字樣式設置1.文本顏色設置2.文本字號設置3.文本字體設置4. 實戰演練5.黃色高亮 一、如何在Markdown中插入表情&#xff1f; 在Markdown中插入表情&#xff08;emoji&#xff09;的方法取決于你使用…

如何提升百度小程序的收錄?百度小程序如何做優化?

? 如何通過百度小程序獲得更多的自然流量&#xff1f;這是做百度小程序肯定要考慮的問題&#xff0c;做百度小程序的目的就是想借助百度生態&#xff0c;做相應的關鍵詞給自己的小程序引流&#xff0c;如何把流量給做起來呢&#xff0c;接下來我從不同的方面給大家進行分析講解…

最新ChatGpt Desktop for Mac 安裝使用教程

1. 下載地址 請點擊鏈接下載 ChatGPT Desktop for MacOS 2. 使用要求 MacOS 版本 14需要時M1芯片的&#xff0c;如果你是因特爾的暫時還還不行 就算下載了也會出現下面的異常 3. 獲取權限資格 目前 ChatGPT MacOS Desktop還不是全量開放的, 如果你沒有收到通知說明你還沒…

在 Dockerfile 中遇到了連接到 pypi.org 超時的問題

看起來你在 Dockerfile 中遇到了連接到 pypi.org 超時的問題。這可能是由于網絡連接問題導致的。你可以嘗試以下方法解決這個問題&#xff1a; 1. 更換鏡像源&#xff1a; 有時候 pypi.org 的訪問會受到地理位置或網絡環境的影響&#xff0c;你可以考慮使用國內的鏡像源來代…

Oracle的ROWID解析

目錄 一、ROWID基礎概念二、ROWID的類型三、ROWID的用途四、注意事項五、管理與監控 Oracle的ROWID是一個非常核心的概念&#xff0c;它代表了一行數據在數據庫中的物理位置標識。 一、ROWID基礎概念 唯一性與不變性&#xff1a;ROWID是每行數據的唯一標識符&#xff0c;它在行…

【Spark】調整hive表在HDFS存的每個文件的大小

配置參數&#xff1a; spark.hadoop.hive.exec.orc.default.stripe.size78643200 spark.hadoop.orc.stripe.size78643200 spark.hadoopRDD.targetBytesInPartition78643200 spark.hadoop.hive.exec.dynamic.partition.modenonstrict spark.sql.sources.partitionOverwriteMode…

ipa 覆蓋算法測試

相關文章 ipa 功能包測試 ipa 分區算法 ipa 分區算法總結&#xff0c;部分算法圖解 ipa 覆蓋算法分析&#xff08;一&#xff09; ipa 覆蓋算法分析&#xff08;二&#xff09; 測試 網上找的地圖&#xff1a; fig.1 測試地圖 opencv fig.2 opencv 顯示的覆蓋路徑 rviz fi…

6.定時器分時復用測量占空比

1.CUBEMAX配置 測量PA6&#xff0c;PA7輸出的占空比&#xff0c;只需要把主要的配置&#xff0c;配置為A6口就行&#xff0c;A7口黃色表示配置不正確&#xff0c;不用管。 2.軟件代碼 TIME.c中找到TIM3的初始化&#xff0c;在后面初始化A7口 void MX_TIM3_Init_PA7(void) {/*…

創新實訓2024.05.25日志:Web應用技術選型

我們的web應用使用python web的fastapi框架&#xff0c;通過uvicorn開啟web服務。 1. refs 官網文檔&#xff1a;FastAPI (tiangolo.com) github&#xff1a;https://github.com/tiangolo/fastapi 2. 環境配置 python:3.11 uvicorn:0.29.0 pip install "uvicorn[stan…

老外賣27刀每月的教程已經更新

用了兩天半的時間&#xff0c;邊學習&#xff0c;邊整理了一份老外的視頻教程&#xff0c;涉及Facebook&#xff0c;YouTube&#xff0c;tiktok等大的流量平臺&#xff0c;有案例&#xff0c;有分析&#xff0c;有如何做。 這個教程是老外講的&#xff0c;沒有什么玄乎的塑造價…

理解矩陣內積與矩陣乘法的區別及其應用

文章目錄 矩陣內積&#xff08;逐元素乘積&#xff09;矩陣內積的用途矩陣乘法&#xff08;矩陣積&#xff09;矩陣乘法的用途區別總結結論 在數據科學、機器學習、計算機圖形學和圖像處理等領域&#xff0c;矩陣運算是非常基礎且重要的操作。然而&#xff0c;矩陣內積和矩陣乘…

【java程序設計期末復習】chapter3 運算符、表達式和語句

運算符、表達式和語句 Java提供了豐富的運算符&#xff0c;如算術運算符、關系運算符、邏輯運算符、位運算符等。 Java語言中的絕大多數運算符和C語言相同&#xff0c;基本語句&#xff0c;如條件分支語句、循環語句等也和C語言類似&#xff0c;因此&#xff0c;本章就主要知識…

聊聊ChatGPT的本質

這是鼎叔的第九十八篇原創文章。行業大牛和剛畢業的小白&#xff0c;都可以進來聊聊。 階段性總結下我對ChatGPT的基礎理解&#xff0c;算是一篇學習思考筆記吧。其中難免有很多不準確的&#xff0c;或過于簡略的地方&#xff0c;將來再迭代學習。 OpenAI做ChatGPT的底層邏輯…

GitLab的原理及應用詳解(六)

本系列文章簡介&#xff1a; 隨著軟件開發的不斷進步和發展&#xff0c;版本控制系統成為了現代軟件開發過程中不可或缺的一部分。而GitLab作為其中一種流行的版本控制工具&#xff0c;在軟件開發領域享有廣泛的應用。GitLab不僅提供了強大的版本控制功能&#xff0c;還集成了項…

如何利用線程池實現互聯網驗證碼保護服務

如何利用線程池實現互聯網驗證碼保護服務 1、業務背景與實現思路2、代碼實操1、業務背景與實現思路 首先介紹一下業務背景,假設我們的系統是一個短視頻播放網站,每個新加入的用戶都需要注冊賬號并綁定手機號。為了驗證用戶手機的正確性,我們的系統會發送一條驗證碼到用戶注…

HBase到底是列式存儲還是行式存儲?

行存和列存 在行存儲的數據庫系統中&#xff0c;一行中的所有字段值都是連續存儲的&#xff1b;在基于行存儲的表中&#xff0c;即使只需要讀取指定列時&#xff0c;也需要先將對應行的數據讀取到內存&#xff0c;再過濾目標列&#xff0c;這樣會導致過多的磁盤IO、內存和時間…

隊列——鏈式存儲

核心思路&#xff1a; 1、首先定義隊列結點&#xff0c;包含數據域和指針域&#xff1b;然后定義鏈式隊列&#xff0c;包含隊列節點類型的隊頭和隊尾指針。 2、初始化&#xff1a;     帶頭結點&#xff1a;給頭結點分配內存&#xff0c;然后隊頭和隊尾指針指向頭結點&…