日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

go系列 锁的初识

發(fā)布時(shí)間:2023/12/13 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go系列 锁的初识 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Go基礎(chǔ)之鎖的初識(shí)

當(dāng)我們的程序就一個(gè)線程的時(shí)候是不需要用到鎖的,但是通常我們實(shí)際的代碼不會(huì)是單個(gè)線程的,所有這個(gè)時(shí)候就需要用到鎖了,那么關(guān)于鎖的使用場(chǎng)景主要涉及到哪些呢?

  • 當(dāng)我們多個(gè)線程在讀相同的數(shù)據(jù)的時(shí)候則是需要加鎖的
  • 當(dāng)我們的程序既有讀又有寫(xiě)的時(shí)候更是需要加鎖的
  • 當(dāng)我們有多個(gè)線程在寫(xiě)的時(shí)候同樣也是需要加鎖

互斥鎖

互斥鎖:同一個(gè)時(shí)刻只有一個(gè)線程能夠拿到鎖

我們先通過(guò)一個(gè)例子來(lái)演示,如果當(dāng)多個(gè)線程同時(shí)更改一個(gè)變量,結(jié)果會(huì)是怎么樣
不加鎖版本

package mainimport ("sync""fmt" )var (//lock sync.Mutexcount intw sync.WaitGroup //用于等待子線程執(zhí)行完之后退出 )func main() {w.Add(1) // 在調(diào)用線程前執(zhí)行w.addgo func(){for i:=0;i<100000;i++{count++}w.Done() //執(zhí)行完 執(zhí)行w.Done}()for i :=0;i<100000;i++{count++}w.Wait() // 最后執(zhí)行w.wait等待所有的線程執(zhí)行完畢f(xié)mt.Println(count)}

當(dāng)我們運(yùn)行多次就可以發(fā)現(xiàn),最后的結(jié)果基本不可能是我們先看到的:200000
我們修改代碼代碼需要加鎖保護(hù)的地方加上鎖,并且這里加的是互斥鎖,修改后的代碼為:

package mainimport ("sync""fmt" )var (lock sync.Mutexcount intw sync.WaitGroup //用于等待子線程執(zhí)行完之后退出 )func main() {w.Add(1) // 在調(diào)用線程前執(zhí)行w.addgo func(){for i:=0;i<100000;i++{lock.Lock()count++lock.Unlock()}w.Done() //執(zhí)行完 執(zhí)行w.Done}()for i :=0;i<100000;i++{lock.Lock()count++lock.Unlock()}w.Wait() // 最后執(zhí)行w.wait等待所有的線程執(zhí)行完畢f(xié)mt.Println(count)}

這次當(dāng)我們多次運(yùn)行的時(shí)候,就能保證我們每次都能看到我們想要的值:200000
接下來(lái)看讀寫(xiě)鎖

讀寫(xiě)鎖

讀寫(xiě)鎖主要用到讀多寫(xiě)少的場(chǎng)景
讀寫(xiě)鎖分為:讀鎖和寫(xiě)鎖

如果自己設(shè)置了一個(gè)寫(xiě)鎖,那么其他讀的線程以及寫(xiě)的線程都拿不到鎖,這個(gè)時(shí)候和互斥鎖的功能相同
如果自己設(shè)置了一個(gè)讀鎖,那么其他寫(xiě)的線程是拿不到鎖的,但是其他讀的線程都是可以拿到這個(gè)鎖

我們把上面的例子代碼進(jìn)行更改:

package mainimport ("sync""fmt" ) var (rwlock sync.RWMutexw sync.WaitGroupcount int )func main() {w.Add(1)go func(){for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個(gè)寫(xiě)鎖count++rwlock.Unlock()}w.Done()}()for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個(gè)寫(xiě)鎖count++rwlock.Unlock()}w.Wait()fmt.Println(count) }

通過(guò)設(shè)置寫(xiě)鎖,我們同樣可以實(shí)現(xiàn)數(shù)據(jù)的一致性
下面是一個(gè)讀鎖的使用例子:

package mainimport ("sync""fmt" )var (rwlock sync.RWMutexw sync.WaitGroupcount int )func main() {w.Add(1)go func(){for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個(gè)寫(xiě)鎖count++rwlock.Unlock()}w.Done()}()for i:=0;i<16;i++{w.Add(1)go func(){rwlock.RLock() //這里定義了一個(gè)讀鎖fmt.Println(count)rwlock.RUnlock() //釋放讀鎖w.Done()}()}w.Wait()fmt.Println(count) }

Go中的原子操作

原子操作,我們則不需加鎖,也能保證數(shù)據(jù)的一致性
并且如果只是計(jì)算,那么原子操作則是最快的

實(shí)例代碼:

package mainimport ("sync"//"time""sync/atomic""fmt" )var (w sync.WaitGroupcount int32 )func main() {w.Add(1)//start := time.Now().UnixNano()go func() {for i:=0;i<1000000;i++{atomic.AddInt32(&count,1)}w.Done()}()for i:=0;i<1000000;i++{atomic.AddInt32(&count,1)}w.Wait()//end := time.Now().UnixNano()//fmt.Println((end- start)/1000/1000)fmt.Println(count) }

?

所有的努力都值得期許,每一份夢(mèng)想都應(yīng)該灌溉!

轉(zhuǎn)載于:https://www.cnblogs.com/flying1819/articles/8832749.html

總結(jié)

以上是生活随笔為你收集整理的go系列 锁的初识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。