Go語言的sync.Once和sync.Cond

一.sync.Once

Once(單次執行)

用途:確保某個操作只執行一次(如初始化配置)

核心方法:Do(f func()):保證 f只執行一次

package mainimport ("fmt""sync"
)var (config map[string]stringonce   sync.Oncewg     sync.WaitGroup
)func loadConfig() {once.Do(func() {fmt.Println("Loading config...")config = map[string]string{"key": "value"}})
}func main() {for i := 0; i < 5; i++ {wg.Add(1)go func() {defer wg.Done() // 確保 goroutine 結束時減少計數器loadConfig()}()}wg.Wait() // 等待所有 goroutine 完成
}

可以確保這個協程只進行一次

二.sync.Cond

sync.Cond 是 golang 標準庫提供的并發協調器,用于支援開放人員在指定條件下阻塞和喚醒協程的操作.

  • Wait():釋放鎖并阻塞,直到被喚醒。
  • Signal():喚醒一個等待的 goroutine。
  • Broadcast():喚醒所有等待的 goroutine。

2.1 數據結構與構造器方法

type Cond struct {// 不可以對其進行值拷貝noCopy noCopy// 一個自旋鎖L Locker// 一個隊列,存放阻塞的goroutinenotify  notifyListchecker copyChecker
}// NewCond returns a new Cond with Locker l.
func NewCond(l Locker) *Cond {return &Cond{L:l}
}

(1)成員變量 noCopy + checker 是一套組合拳,保證 Cond 在第一次使用后不允許被復制;

(2)核心變量 L,一把鎖,用于實現阻塞操作;

(3)核心變量 notify,阻塞鏈表,分別存儲了調用 Cond.Wait() 方法的次數、goroutine 被喚醒的次數、一把系統運行時的互斥鎖以及鏈表的頭尾節點.

type notifyList struct {wait   uint32notify uint32lock   uintptr // key field of the mutexhead   unsafe.Pointertail   unsafe.Pointer
}

2.2 Cond.Wait

作用:把當前這個持有鎖的goroutine,釋放鎖,陷入一個被動阻塞的狀態,加入阻塞隊列里面。

什么時候被喚醒呢?

當有其他的goroutine也持有這個Cond的引用,使用Signal函數的時候,會首先喚醒隊首的goroutine

通過這個機制就可以實現異步goroutine的協調,比如需要某一個goroutine實現了某一個動作,另外一個goroutine才可以繼續執行的一個場景。

使用的前置條件

看下面的代碼我們會發現,它有一個解鎖的操作,所以在調用他之前,必須是加鎖的狀態,只有這樣才可以執行,然后陷入被動阻塞的狀態,阻塞喚醒之后,才會重新加鎖。

func (c *Cond) Wait() {c.checker.check()t := runtime_notifyListAdd(&c.notify)c.L.Unlock()runtime_notifyListWait(&c.notify, t)c.L.Lock()
}

(1)檢查 Cond 是否在使用過后被拷貝,是則 panic;

(2)該 Cond 阻塞鏈表 wait 統計數加 1;

(3)當前協程釋放鎖,因為接下來即將被操作系統 park;

(4)將當前協程包裝成節點,添加到 Cond 的阻塞隊列當中,并調用 park 操作將當前協程掛起;

(5)協程被喚醒后,重新嘗試獲取鎖.

2.3 Cond.Signal

作用:就是喚醒隊首的goroutine喚醒

func (c *Cond) Signal() {c.checker.check()runtime_notifyListNotifyOne(&c.notify)
}

(1)檢查 Cond 是否在首次使用后被拷貝,是則 panic;

(2)該 Cond 阻塞鏈表 notify 統計數加 1;

(3)從頭開始遍歷阻塞鏈表,喚醒一個等待時間最長的 goroutine.

2.4 Cond.BroadCast

作用:就是將阻塞隊列里面的所有goroutine都進行喚醒。

func (c *Cond) Broadcast() {c.checker.check()runtime_notifyListNotifyAll(&c.notify)
}

(1)檢查 Cond 是否在首次使用后被拷貝,是則 panic;

(2)取 wait 值賦值給 notify;

(3)喚醒阻塞鏈表所有節點.

2.5 使用案例

package mainimport ("fmt""sync""time"
)func main() {var mu sync.Mutexcond := sync.NewCond(&mu)// 共享狀態isReady := false// 等待條件的goroutinego func() {fmt.Println("等待者: 等待條件滿足...")cond.L.Lock()defer cond.L.Unlock()// 使用循環防止虛假喚醒for !isReady {cond.Wait() // 釋放鎖并阻塞,喚醒時會重新獲得鎖fmt.Println("等待者: 被喚醒,檢查條件")}fmt.Println("等待者: 條件已滿足!")}()// 改變條件的goroutinego func() {time.Sleep(2 * time.Second) // 模擬耗時操作fmt.Println("觸發者: 準備改變條件...")cond.L.Lock()isReady = truecond.L.Unlock()fmt.Println("觸發者: 發送通知")cond.Signal() // 喚醒一個等待的goroutine}()time.Sleep(3 * time.Second) // 等待所有goroutine完成
}

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

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

相關文章

java整合itext pdf實現自定義PDF文件格式導出

springBoot結合itext pdf實現自定義PDF文件格式導出背景需求&#xff1a;使用PDF導出指定人員對應周次的打卡記錄&#xff0c;每周對應星期幾打卡過就打“√”。如下圖&#xff1a;1、導入依賴導入itextpdf依賴<!-- itex PDF --> <dependency><groupId>…

從0開始學習計算機視覺--Day07--神經網絡

當我們輸入的變量是一個比較大的向量&#xff08;比如有4096項&#xff09;&#xff0c;函數是求返回輸入的最大值&#xff0c;要求的權重矩陣的梯度就是4096 * 4096的大小&#xff0c;而實際上我們的輸入往往都不只有一個向量&#xff0c;那如果向量有一百個的話&#xff0c;是…

MySQL存儲過程全解析

1、存儲過程的概念 存儲過程是事先經過編譯并存儲在數據庫中的一段sql語句的集合&#xff0c;調用存儲過程可以簡化應用開發人員的很多工作&#xff0c;減少數據在數據庫和應用服務器之間的傳輸&#xff0c;對于提高數據處理效率是很有好處。 2、存儲過程的優點 存儲過程是通…

后端密碼加密:守護用戶數據的鋼鐵長城

&#x1f512;“系統被拖庫了&#xff01;” 這可能是開發者最恐懼的噩夢。而當用戶密碼以明文暴露時&#xff0c;災難將席卷每個用戶——密碼重用的慣性會讓黑客輕松攻破他們在其他平臺的賬戶。作為后端開發者&#xff0c;我們握有守護用戶安全的第一道鑰匙&#xff1a;科學的…

Flutter 3.29+使用isar構建失敗

執行命令&#xff1a;flutter build apk --release 報錯 Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!FAILURE: Build failed with an exception. …

SQL 轉 Java 實體類工具

拿到數據庫建表語句后怎么高效寫 Java 實體類&#xff1f;這款工具直接幫你全自動生成&#xff01; 作為一名后端 Java 工程師&#xff0c;你是不是也經歷過以下情況&#xff1a; ? 拿到一份完整的建表 SQL&#xff0c;卻要手動寫 Java Bean ? 字段幾十個&#xff0c;嵌套復…

創客匠人視角下:創始人 IP 打造與知識變現的深度耦合路徑

在知識經濟蓬勃發展的當下&#xff0c;創始人 IP 打造與知識變現的融合已成為行業破局關鍵。創客匠人作為深耕知識付費賽道多年的服務平臺&#xff0c;其創始人老蔣提出的 “土壤構建能力” 理論&#xff0c;為理解這一融合邏輯提供了獨特視角。從本質來看&#xff0c;創始人 I…

【網絡協議安全】任務13:ACL訪問控制列表

目錄 一、概念 1、前言 2、應用場景 3、ACL分類 基于ACL標識方法的劃分 基于對IPv4和IPv6支持情況的劃分 基于ACL規則定義方式的劃分 4、ACL的基本原理 ACL的組成 ACL的匹配機制 5、ACL常用匹配原則 6、ACL常用的匹配項 生效時間段 IP承載的協議類型 源/目的IP…

TensorFlow 安裝使用教程

一、TensorFlow 簡介 TensorFlow 是由 Google 開發的開源深度學習框架&#xff0c;支持數據流圖計算&#xff0c;可運行于 CPU/GPU/TPU。它被廣泛應用于語音識別、圖像處理、自然語言處理等多個 AI 領域。 二、安裝 TensorFlow 2.1 pip 安裝&#xff08;默認 CPU 版本&#x…

騰訊云認證考試報名 - TDSQL數據庫交付運維專家(TCCE MySQL版)

數據庫交付運維專家- 騰訊云TDSQL(MySQL版) 適合人群&#xff1a; 適合TDSQL(MySQL版)各組件擴縮容、運維、性能優化、故障解決、壓力測試等數據庫開發、運維、管理人員。 認證考試&#xff1a; 單選*40道多選*20道上機*20道 考試時長&#xff1a; 理論考試120分鐘,上機考試…

webUI平替應用,安裝簡單,功能齊全

前言 在安裝本地大模型后&#xff0c;我們都會為大模型安裝一個用戶界面&#xff0c;這樣就可以實現語音輸入&#xff0c;對話保存&#xff0c;微調&#xff0c;構建本地知識庫等高階功能。 目前最火的本地大模型UI&#xff0c;就是gihub上的webUI&#xff0c;但他不僅依賴較…

【Maven】Maven核心機制的 萬字 深度解析

Maven核心機制的萬字深度解析一、依賴管理機制全解&#xff08;工業級依賴治理方案&#xff09;1. 坐標體系的本質與設計哲學2. 依賴傳遞與仲裁算法的工程實現**沖突仲裁核心算法**企業級仲裁策略3. Scope作用域的類加載隔離原理4. 多級倉庫體系架構設計二、構建生命周期底層原…

暑期前端訓練day4

今天主要是有關周賽的&#xff0c;比賽的時候是用c寫的并且是 ak了&#xff0c;但是就是想用js再復盤一下&#xff0c;也不能只是圖一時之爽&#xff0c;如果是換在實際的場景里面我是不是只會用 c快速寫出來。 最近也要從js逐漸轉向ts&#xff0c;感覺Ts才是主旋律&#xff0c…

轉Go學習筆記(2)進階

前置&#xff1a;轉Go學習筆記1語法入門 目錄Golang進階groutine協程并發概念梳理創建goroutine語法channel實現goroutine之間通信channel與range、selectGoModulesGo Modules與GOPATHGo Modules模式用Go Modules初始化項目修改模塊的版本依賴關系Go Modules 版本號規范vendor …

無人機3控接力模式技術分析

一、運行方式 1. 接力控制流程 位置觸發切換&#xff1a;飛控中心實時監測無人機位置&#xff0c;當進入預設的切換路線&#xff08;如靠近下一個機庫或控制器覆蓋范圍&#xff09;時&#xff0c;觸發切換流程。 控制權請求與驗證&#xff1a; 當前控制器&#xff08…

Actor Critic對比PGValue-Based

目錄 回顧一下policy gradient&#xff1a; QAC算法&#xff1a; A2C- advantage actor critic 問題&#xff1a; 1. 為什么要結合起來&#xff0c;能解決什么問題&#xff1f; 1. 策略梯度 (PG) 的優勢與核心問題 2. 基于價值方法 (Value-Based) 的優勢與局限性 3. 潛…

buuctf-re

1.findKey 打開是C而且有點亂,所以找關鍵步驟有一個加密進去是不能反編譯的,有花指令, 這里有重復的部分把下面的NOP掉,重新定義函數’p’ 之后分析邏輯, // positive sp value has been detected, the output may be wrong! int __userpurge sub_40191F<eax>(int a1&l…

RuoYi、Vue CLI 和 uni-app 結合構建跨端全家桶方案

將 RuoYi、Vue CLI 和 uni-app 結合構建跨端全家桶方案&#xff0c;可以實現一套代碼管理后臺系統&#xff08;PC&#xff09;和移動端應用&#xff08;H5/小程序/App&#xff09;。以下是整合思路和關鍵步驟&#xff1a; 技術棧分工 RuoYi&#xff1a;后端框架&#xff08;Spr…

二十九、windows系統安全---windows注冊表安全配置

環境 windows server 2012 原理 注冊表簡介: 注冊表&#xff08;Registry&#xff0c;繁體中文版Windows操作系統稱之為登錄檔&#xff09;是Microsoft Windows中的一個重要的數據庫&#xff0c;用于存儲系統和應用程序的設置信息。早在Windows 3.0推出OLE技術的時候&#…

Android 一幀繪制流程

Android 一幀繪制流程揭秘&#xff1a;主線程與 RenderThread 的雙人舞 核心目標&#xff1a;60幀/秒的絲滑體驗&#xff0c;意味著每幀必須在16.67ms內完成所有工作&#xff01; 想象一下屏幕刷新就像放映電影&#xff0c;一幀接一幀。Android系統為了播放這“電影”&#xff…