go系列 锁的初识
Go基礎之鎖的初識
當我們的程序就一個線程的時候是不需要用到鎖的,但是通常我們實際的代碼不會是單個線程的,所有這個時候就需要用到鎖了,那么關于鎖的使用場景主要涉及到哪些呢?
- 當我們多個線程在讀相同的數據的時候則是需要加鎖的
- 當我們的程序既有讀又有寫的時候更是需要加鎖的
- 當我們有多個線程在寫的時候同樣也是需要加鎖
互斥鎖
互斥鎖:同一個時刻只有一個線程能夠拿到鎖
我們先通過一個例子來演示,如果當多個線程同時更改一個變量,結果會是怎么樣
不加鎖版本
當我們運行多次就可以發現,最后的結果基本不可能是我們先看到的:200000
我們修改代碼代碼需要加鎖保護的地方加上鎖,并且這里加的是互斥鎖,修改后的代碼為:
這次當我們多次運行的時候,就能保證我們每次都能看到我們想要的值:200000
接下來看讀寫鎖
讀寫鎖
讀寫鎖主要用到讀多寫少的場景
讀寫鎖分為:讀鎖和寫鎖
如果自己設置了一個寫鎖,那么其他讀的線程以及寫的線程都拿不到鎖,這個時候和互斥鎖的功能相同
如果自己設置了一個讀鎖,那么其他寫的線程是拿不到鎖的,但是其他讀的線程都是可以拿到這個鎖
我們把上面的例子代碼進行更改:
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() // 這里定義了一個寫鎖count++rwlock.Unlock()}w.Done()}()for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個寫鎖count++rwlock.Unlock()}w.Wait()fmt.Println(count) }通過設置寫鎖,我們同樣可以實現數據的一致性
下面是一個讀鎖的使用例子:
Go中的原子操作
原子操作,我們則不需加鎖,也能保證數據的一致性
并且如果只是計算,那么原子操作則是最快的
實例代碼:
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) }?
所有的努力都值得期許,每一份夢想都應該灌溉!轉載于:https://www.cnblogs.com/flying1819/articles/8832749.html
總結
- 上一篇: 公共平台服务治理与鉴权
- 下一篇: 回信,我的好朋友王一涵