Go語(yǔ)言中樂(lè)觀鎖與悲觀鎖的具體使用
改變一個(gè)數(shù)值的三個(gè)步驟
- 把想修改的數(shù)值從某個(gè)地方取出來(lái)
- 將取出來(lái)的數(shù)值修改為期望值
- 把修改后的數(shù)值保存到原來(lái)的地方
問(wèn)題
如果在做第2步時(shí),有另一個(gè)過(guò)程(進(jìn)程或線程)對(duì)同一個(gè)數(shù)值進(jìn)行同樣的操作(取值、修改),那么當(dāng)這兩個(gè)過(guò)程都要做第3步的時(shí)候,就肯定有一個(gè)過(guò)程是白干活的。
悲觀鎖
悲觀的鎖總認(rèn)為會(huì)發(fā)生并發(fā)問(wèn)題,屬于保守派。
如果想修改一個(gè)數(shù)值,立馬給這個(gè)數(shù)值上一把鎖,標(biāo)明這個(gè)數(shù)值正在被修改,誰(shuí)也不能修改了;然后才開(kāi)始三步走,在三步走的過(guò)程結(jié)束以后,再把鎖解除。
當(dāng)有其他過(guò)程想要修改同一個(gè)數(shù)值時(shí),看到了鎖就不進(jìn)行三步走了,而是選擇等待;當(dāng)鎖被解除了,自己在數(shù)值也加一把鎖,然后開(kāi)始三步走,在三個(gè)步驟走完了,也把鎖解除。
樂(lè)觀鎖
樂(lè)觀的鎖總認(rèn)為不會(huì)發(fā)生并發(fā)問(wèn)題,屬于樂(lè)天派。
修改數(shù)據(jù)時(shí)不加鎖,正常進(jìn)行1、2步,在進(jìn)行第3步的時(shí)候,確認(rèn)一下數(shù)值是否進(jìn)行了修改,如果被修改過(guò),放棄修改,重新走一遍1、2、3步(或者放棄對(duì)數(shù)值進(jìn)行修改)。
Go語(yǔ)言中的樂(lè)觀鎖與悲觀鎖
sync/atomic
Go語(yǔ)言有一個(gè)atomic包,可以在不形成臨界區(qū)和創(chuàng)建互斥量的情況下完成并發(fā)安全的值替換操作,這個(gè)包應(yīng)用的便是樂(lè)觀鎖的原理
但是這個(gè)包只支持int32/int64/uint32/uint64/uintptr這幾種數(shù)據(jù)類型的一些基礎(chǔ)操作,如增減、交換、載入、存儲(chǔ)等
sync
Go語(yǔ)言中的sync包提供了各種鎖,如果使用了這個(gè)包,基本就以悲觀鎖的工作模式了
go代碼示例
package main import ( "fmt" "sync" "sync/atomic" "time" ) var ( x int64 mu sync.Mutex wg sync.WaitGroup ) // 普通函數(shù), 并發(fā)不安全 func Add() { x++ wg.Done() } // 互斥鎖, 并發(fā)安全,性能低于原子操作 func muAdd() { mu.Lock() x++ mu.Unlock() wg.Done() } // 原子操作,并發(fā)安全,性能高于互斥鎖,只針對(duì)go中的一些基本數(shù)據(jù)類型使用 func AmAdd() { atomic.AddInt64(&x, 1) wg.Done() } func main() { // 原子操作atomic包 // 加鎖操作涉及到內(nèi)核態(tài)的上下文切換, 比較耗時(shí),代價(jià)高 // 針對(duì)基本數(shù)據(jù)類型我們還可以使用原子操作來(lái)保證并發(fā)安全 // 因?yàn)樵硬僮魇莋o語(yǔ)言提供的方法,我們?cè)谟脩魬B(tài)就可以完成,因此性能比加鎖操作更好 // go語(yǔ)言的原子操作由內(nèi)置的庫(kù),sync/atomic完成 start := time.Now() for i := 0; i < 10000; i++ { wg.Add(1) go Add() // 普通版Add函數(shù)不是并發(fā)安全的 // go muAdd() // 加鎖版Add函數(shù),是并發(fā)安全的, 但是加鎖性能開(kāi)銷大 // go AmAdd() // 原子操作版Add函數(shù),是并發(fā)安全的,性能優(yōu)于加鎖版 } end := time.Now() wg.Wait() fmt.Println(x) fmt.Println(end.Sub(start)) }
到此這篇關(guān)于Go語(yǔ)言中樂(lè)觀鎖與悲觀鎖的具體使用的文章就介紹到這了,更多相關(guān)Go語(yǔ)言 樂(lè)觀鎖與悲觀鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go語(yǔ)言開(kāi)發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法
這篇文章主要為大家介紹了go語(yǔ)言開(kāi)發(fā)中如何優(yōu)雅得關(guān)閉協(xié)程方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Golang 并發(fā)控制模型的實(shí)現(xiàn)
Go控制并發(fā)有三種經(jīng)典的方式,使用?channel?通知實(shí)現(xiàn)并發(fā)控制、使用 sync 包中的?WaitGroup?實(shí)現(xiàn)并發(fā)控制、使用?Context?上下文實(shí)現(xiàn)并發(fā)控制,下面就來(lái)介紹一下2024-08-08Golang實(shí)現(xiàn)帶優(yōu)先級(jí)的select
這篇文章主要為大家詳細(xì)介紹了如何在Golang中實(shí)現(xiàn)帶優(yōu)先級(jí)的select,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Golang有一定的幫助,需要的可以參考一下2023-04-04Go語(yǔ)言導(dǎo)出內(nèi)容到Excel的方法
這篇文章主要介紹了Go語(yǔ)言導(dǎo)出內(nèi)容到Excel的方法,涉及Go語(yǔ)言操作excel的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02詳解Golang如何實(shí)現(xiàn)一個(gè)環(huán)形緩沖器
環(huán)形緩沖器(ringr?buffer)是一種用于表示一個(gè)固定尺寸、頭尾相連的緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu),適合緩存數(shù)據(jù)流。本文將利用Golang實(shí)現(xiàn)一個(gè)環(huán)形緩沖器,需要的可以參考一下2022-09-09go語(yǔ)言實(shí)現(xiàn)十大常見(jiàn)的排序算法示例
這篇文章主要為大家介紹了go語(yǔ)言實(shí)現(xiàn)十大常見(jiàn)的排序算法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08