go系列 锁的初识
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ì)是怎么樣
不加鎖版本
當(dāng)我們運(yùn)行多次就可以發(fā)現(xiàn),最后的結(jié)果基本不可能是我們先看到的:200000
我們修改代碼代碼需要加鎖保護(hù)的地方加上鎖,并且這里加的是互斥鎖,修改后的代碼為:
這次當(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è)讀鎖的使用例子:
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é)
- 上一篇: 公共平台服务治理与鉴权
- 下一篇: 回信,我的好朋友王一涵