條件變量 sync.Cond

sync.Cond 條件變量是基于互斥鎖的,它必須有互斥鎖的支撐才能發揮作用。

  • sync.Cond 條件變量用來協調想要訪問共享資源的那些線程,當共享資源的狀態發生變化的時候,它可以用來通知被互斥鎖阻塞的線程
  • 條件變量的初始化離不開互斥鎖,并且它的方法也是基于互斥鎖的
  • 條件變量有三個方法,等待通知(wait),單發通知(signal),廣播通知(broadcast)。當互斥鎖鎖定時,可以進行等待通知;當互斥鎖解鎖時,可以進行單發通知和廣播通知。
var mailbox uint8
var lock sync.RWMutex
sendCond := sync.NewCond(&lock)
recvCond := sync.NewCond(lock.RLocker())

有幾個點需要知道

  • sync.Cond 通過sync.NewCond(sync.Locker)初始化,初始化函數需要一個sync.Locker的參數值
  • sync.Locker其實是一個接口,包含Lock()和Unlock()方法。sync.Mutex和sync.RWMutex都有Lock和Unlock方法,只不過它們都是指針方法。因此,這兩個類型的指針類型才是sync.Locker接口的實現類型
  • 通過lock.RLock()獲得讀鎖,這個讀鎖能調用lock變量的RLock和RUnlock方法,實現對讀鎖的解鎖和鎖定。

生產者,這里看作向mailbox產生值的對象

lock.Lock()
for mailbox == 1 {sendCond.Wait()
}
mailbox = 1
lock.Unlock()
recvCond.Signal()

消費者,向mailbox取值的對象

lock.RLock()
for mailbox == 0 {recvCond.Wait()
}
mailbox = 0
lock.RUnlock()
sendCond.Signal()

條件變量的Wait方法主要做了四件事。

  • 把調用它的 goroutine(也就是當前的 goroutine)加入到當前條件變量的通知隊列中。
  • 解鎖當前的條件變量基于的那個互斥鎖。
  • 讓當前的 goroutine 處于等待狀態,等到通知到來時再決定是否喚醒它。此時,這個 goroutine 就會阻塞在調用這個Wait方法的那行代碼上。
  • 如果通知到來并且決定喚醒這個 goroutine,那么就在喚醒它之后重新鎖定當前條件變量基于的互斥鎖。自此之后,當前的 goroutine 就會繼續執行后面的代碼了。

if語句只會對共享資源的狀態檢查一次,而for語句卻可以做多次檢查,直到這個狀態改變為止。那為什么要做多次檢查呢?這主要是為了保險起見。如果一個 goroutine 因收到通知而被喚醒,但卻發現共享資源的狀態,依然不符合它的要求,那么就應該再次調用條件變量的Wait方法,并繼續等待下次通知的到來。

在 Go 語言中,我們需要用sync.NewCond函數來初始化一個sync.Cond類型的條件變量。

sync.NewCond函數需要一個sync.Locker類型的參數值。

sync.Mutex類型的值以及sync.RWMutex類型的值都可以滿足這個要求。都可以滿足這個要求。另外,后者的RLocker方法可以返回這個值中的讀鎖,也同樣可以作為sync.NewCond函數的參數值,如此就可以生成與讀寫鎖中的讀鎖對應的條件變量了。

條件變量的Wait方法需要在它基于的互斥鎖保護下執行,否則就會引發不可恢復的 panic。此外,我們最好使用for語句來檢查共享資源的狀態,并包裹對條件變量的Wait方法的調用。

不要用if語句,因為它不能重復地執行”檢查狀態 - 等待通知 - 被喚醒“的這個流程。重復執行這個流程的原因是,一個因等待通知,而被阻塞的 goroutine,可能會在共享資源的狀態不滿足其要求的情況下被喚醒。

條件變量的Signal方法只會喚醒一個因等待通知而被阻塞的 goroutine,而它的Broadcast方法卻可以喚醒所有為此而等待的 goroutine。后者比前者的適應場景要多得多。

這兩個方法并不需要受到互斥鎖的保護,我們也最好不要在解鎖互斥鎖之前調用它們。還有,條件變量的通知具有即時性。當通知被發送的時候,如果沒有任何 goroutine 需要被喚醒,那么該通知就會立即失效。

轉載于:https://www.cnblogs.com/linyihai/p/10253339.html

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

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

相關文章

JDK內置工具使用

JDK內置工具使用 一、javah命令(C Header and Stub File Generator) 二、jps命令(Java Virtual Machine Process Status Tool) 三、jstack命令(Java Stack Trace) 四、jstat命令(Java Virtual Machine Statistics Monitoring Tool) 五、jmap命令(Java Memory Map) 六、jinfo命令…

mall整合RabbitMQ實現延遲消息

摘要 本文主要講解mall整合RabbitMQ實現延遲消息的過程,以發送延遲消息取消超時訂單為例。RabbitMQ是一個被廣泛使用的開源消息隊列。它是輕量級且易于部署的,它能支持多種消息協議。RabbitMQ可以部署在分布式和聯合配置中,以滿足高規模、高可…

競價打板的關鍵點

競價打板,主要是速度,其他不重要的,如果為了當天盈利大,失去競價打板的本質含義,因為競價可以買到,盤中買不到,才是競價打板的目的,也就是從競價打板的角度看,主要是看習…

Java常見的幾種內存溢出及解決方法

Java常見的幾種內存溢出及解決方法【情況一】:java.lang.OutOfMemoryError:Javaheapspace:這種是java堆內存不夠,一個原因是真不夠(如遞歸的層數太多等),另一個原因是程序中有死循環;如果是java…

docker操作之mysql容器

1、創建宿主機器的掛載目錄 /opt/docker/mysql/conf /opt/docker/mysql/data /opt/docker/mysql/logs 2、創建【xxx.cnf】配置文件,內容如下所示: [mysqld]#服務唯一Idserver-id 1port 3306log-error /var/log/mysql/error.log #只能用IP地址skip_nam…

Windows10系統下wsappx占用CPU資源過高?wsappx是什么?如何關閉wsappx進程?

在Windows10系統開機的時候,wsappx進程占用的CPU資源非常高,導致電腦運行速度緩慢,那么我們如何關閉wsappx進程,讓電腦加快運行速度呢?下面就一起來看一下操作的方法吧。 【現象】 1、先來看一下電腦剛開機的時候&…

如何通過Windows Server 2008 R2建立NFS存儲

如何通過Windows Server 2008 R2建立NFS存儲在我們日常工作的某些實驗中,會需要使用存儲服務器。而硬件存儲成本高,如StarWind之類的iSCSI軟存儲解決方案需要單獨下載服務器端程序,且配置比較繁瑣,令很多新手們很是頭疼。事實上&a…

python-windows安裝相關問題

1.python的環境配置,有些時候是沒有配置的,需要在【系統環境】-【path】里添加。 2.安裝pip:從官網下載pip包,然后到包目錄》python setup.py install 安裝 3.安裝scrapyd:正常使用pip3 install scrapyd安裝不起&…

hdu 1542/1255 Atlantis/覆蓋的面積

1542 1255 兩道掃描線線段樹的入門題。 基本沒有什么區別&#xff0c;前者是模板&#xff0c;后者因為是求覆蓋次數至少在兩次以上的&#xff0c;這個同樣是具有并集性質的&#xff0c;所以把cover的判斷條件更改一下就可以了qwq。 hdu1542 代碼如下&#xff1a; #include<i…

使用了JDK自帶的jconsole查看Tomcat運行情況

最近對公司的項目進行JVM調優&#xff0c;使用了JDK自帶的jconsole查看Tomcat運行情況&#xff0c;記錄下配置以便以后參考&#xff1a;首先&#xff0c;修改Tomcat的bin目錄下的catalina.bat文件&#xff0c;在JAVA_OPTS變量中添加下面四行&#xff0c;即可set JAVA_OPTS %JAV…

jvm02

java虛擬機內存管理 每個線程就是一個順序的執行單元&#xff0c;線程共享區即多個線程共享同一塊區域&#xff0c;線程獨占區即每個線程都有自己的虛擬機棧&#xff0c;本地方法棧&#xff0c;程序計數器。 程序計數器是一個比較小的內存空間&#xff0c;可以看作是當前線程所…

搭建svn管理平臺

安裝svn服務器&#xff1a;yum -y install subversion創建svn的目錄&#xff1a;mkdir -p /data/svn初始化svn目錄&#xff1a;svnadmin create /data/svnconf下的三個目錄介紹&#xff1a;authz&#xff1a;控制權限,創建用戶。密碼在passwd創建 passwd&#xff1a;密碼文件&…

Oracle dataguard 正常切換和應急切換

Oracle dataguard 正常切換和應急切換oracle dataguard提供異地容災方案,能有效的防止單點故障和提供高可用技術,這里介紹dataguard正常主備切換和應急切換&#xff08;應急切換模擬主庫出現問題無法還原,備庫脫離dataguard接管主庫對外提供服務&#xff09;1&#xff09;Oracl…

好程序員web前端分享JS引擎的執行機制

好程序員web前端分享JS引擎的執行機制&#xff0c;請先著重牢記兩點&#xff01;JS是單線程語言。JS的EventLoop是JS的執行機制。深入了解JS的執行&#xff0c;就等于深入了解JS里的eventloop。1、靈魂三問&#xff1a;JS為什么是單線程的?為什么需要異步?單線程又是如何實現…

shutil模塊、json和pickle模塊

shutil模塊&#xff1a; 高級的文件、文件夾、壓縮包處理模塊 json和pickle模塊 之前學過eval內置方法可以將一個字符串轉化成Python對象&#xff0c;但eval方法是有局限性的&#xff0c;對于普通的數據類型&#xff0c;json.loads、eval都可以使用&#xff0c;但遇到特殊類型的…

每日一問:LayoutParams 你知道多少?

前面的文章中著重講解了 View 的測量流程。其中我提到了一句非常重要的話&#xff1a;**View 的測量匡高是由父控件的 MeasureSpec 和 View 自身的 LayoutParams 共同決定的。**我們在前面的 每日一問&#xff1a;談談對 MeasureSpec 的理解 把 MeasureSpec 的重點進行了講解&a…

kuangbin專題十六 KMP擴展KMP HDU2594 Simpsons’ Hidden Talents

Homer: Marge, I just figured out a way to discover some of the talents we weren’t aware we had. Marge: Yeah, what is it? Homer: Take me for example. I want to find out if I have a talent in politics, OK? Marge: OK. Homer: So I take some politician’s na…

SNI: 實現多域名虛擬主機的SSL/TLS認證

為什么80%的碼農都做不了架構師&#xff1f;>>> 一. 介紹 早期的SSLv2根據經典的公鑰基礎設施PKI(Public Key Infrastructure)設計&#xff0c;它默認認為&#xff1a;一臺服務器&#xff08;或者說一個IP&#xff09;只會提供一個服務&#xff0c;所以在SSL握手時…

echo(),print(),print_r(),var_dump()的區別

echo可以一次輸出多個值&#xff0c;多個值之間用逗號分隔。echo是語言結構(language construct)&#xff0c;而并不是真正的函數&#xff0c;因此不能作為表達式的一部分使用。echo是php的內部指令&#xff0c;不是函數&#xff0c;無返回值。 print()&#xff1a;函數print()…

我心目中的牛程序員、我們可以對比看看(人家還是看多年朋友面子上才肯幫忙1周,至少需支付1萬元辛苦費)...

為什么80%的碼農都做不了架構師&#xff1f;>>> 最近碰到客戶整個網站改版的需要&#xff0c;非常短的時間里只有1周時間里&#xff0c;需要把整個B2C網站徹底的進行版面&#xff0c;我自己估算了一下&#xff0c;就是往死里干一天工作48個小時&#xff0c;1周也干…