互斥鎖Mutex和讀寫鎖RWMutex區別

2021-10-07 05:46:31 字數 4535 閱讀 9318

引用一下golang互斥鎖和讀寫鎖效能分析中關於互斥鎖和讀寫鎖的定義,比較清楚

1.互斥鎖有兩種操作,獲取鎖和釋放鎖

2.當有乙個goroutine獲取了互斥鎖後,任何goroutine都不可以獲取互斥鎖,只能等待這個goroutine將互斥鎖釋放

3.互斥鎖適用於讀寫運算元量差不多的情況

4.讀寫都可以放入互斥鎖中

1.讀寫鎖有四種操作 讀上鎖 讀解鎖 寫上鎖 寫解鎖

2.寫鎖最多有乙個,讀鎖可以有多個(最大個資料說和cpu個數有關)

3.寫鎖的優先順序高於讀鎖,這是因為為了防止讀鎖過多,寫鎖一直堵塞的情況發生

4.當有乙個goroutine獲得寫鎖時,其他goroutine不可以獲得讀鎖或者寫鎖,直到這個寫鎖釋放

5.當有乙個goroutine獲得讀鎖時,其他goroutine可以獲得讀鎖,但是不能獲得寫鎖。所以由此也可得知,如果當乙個goroutine希望獲取寫鎖時,不斷地有其他goroutine在獲得讀鎖和釋放讀鎖會導致這個寫鎖一直處於堵塞狀態,所以讓寫鎖的優先順序高於讀鎖可以避免這種情況,

6.讀寫鎖適用於讀多寫少的情景。

7.在讀取操作多的情況下,比如現在有三個goroutine:g1,g2,g3都想要讀取一段資料a,我們如果用互斥鎖的話,就是以下的情形:g1先加鎖,然後讀取a,然後釋放;然後g2加鎖,讀取a,釋放;g3加鎖,讀取a,然後釋放…這個操作是序列的,由於每個goroutine都需要排隊等待前乙個goroutine釋放鎖,所以效率顯然不高;但是如果這個時候我們用讀寫鎖就可以讓g1,g2,g3同時讀a,就可以大大的提公升效率。

8.寫操作只能放在寫鎖中,讀操作可以放在讀寫鎖中,但是放在寫鎖中肯定併發效率低

在本機上跑博主提供的原**時,結果與博主相反

package main

import

("fmt"

"sync"

"time"

)const maxnum =

1000

//map的大小

const locknum =

1e7//加鎖次數

var lock sync.mutex //互斥鎖

var rwlock sync.rwmutex //讀寫鎖

var lock_map map

[int

]int

//互斥鎖map

var rwlock_map map

[int

]int

//讀寫鎖map

func

main()

var rwlock_w =

&sync.waitgroup

lock_w.

add(locknum)

rwlock_w.

add(locknum)

lock_ch :=

make

(chan

int,

10000

) rwlock_ch :=

make

(chan

int,

10000

) lock_map =

make

(map

[int

]int

, maxnum)

rwlock_map =

make

(map

[int

]int

, maxnum)

init_map

(lock_map, rwlock_map)

time1 := time.

now(

)for i :=

0; i < locknum; i++

lock_w.

wait()

time2 := time.

now(

)for i :=

0; i < locknum; i++

rwlock_w.

wait()

time3 := time.

now(

) fmt.

println

("lock time:"

, time2.

sub(time1)

.string()

) fmt.

println

("rwlock time:"

, time3.

sub(time2)

.string()

)}func

init_map

(a map

[int

]int

, b map

[int

]int)}

func

test1

(ch chan

int, i int

, mymap map

[int

]int

, w *sync.waitgroup)

intfunc

test2

(ch chan

int, i int

, mymap map

[int

]int

, w *sync.waitgroup)

int

out:

lock time: 3.6869219s

rwlock time: 2.7925313s

但是可以看到二者的數量級在併發數達到1e7時仍然比較接近

下面我們增加chan傳遞(通用情景),同時增加任務中的耗時(這會增加互斥鎖的序列負擔)

package main

import

("fmt"

"sync"

"time"

)const maxnum =

1000

//map的大小

const locknum =

1e5//加鎖次數

var lock sync.mutex //互斥鎖

var rwlock sync.rwmutex //讀寫鎖

var lock_map map

[int

]int

//互斥鎖map

var rwlock_map map

[int

]int

//讀寫鎖map

func

main()

gofunc()

()for i :=

range lock_ch

fmt.

printf

("chan id sum %d\n"

, count1)

time2 := time.

now(

)for i :=

0; i < locknum; i++

gofunc()

()for i :=

range rwlock_ch

fmt.

printf

("chan id sum %d\n"

, count2)

time3 := time.

now(

) fmt.

println

("lock time:"

, time2.

sub(time1)

.string()

) fmt.

println

("rwlock time:"

, time3.

sub(time2)

.string()

)}func

init_map

(a map

[int

]int

, b map

[int

]int)}

func

test1

(ch chan

int, i int

, mymap map

[int

]int

, w *sync.waitgroup)

intfunc

test2

(ch chan

int, i int

, mymap map

[int

]int

, w *sync.waitgroup)

int

out:

chan id sum 4999950000

chan id sum 4999950000

lock time: 2m50.2909581s

rwlock time: 124.6928ms

可以看到兩種鎖明顯不在乙個數量級上

將互斥鎖換為讀寫鎖的寫鎖,結果與之前測試相同

讀寫鎖在多讀的時候,由於其避免了互斥鎖的序列性,效能上遠優於互斥鎖

互斥鎖和讀寫鎖

互斥鎖的型別 對資源的訪問是互斥的,即執行緒a對資源加鎖後,在a解鎖前,其他執行緒不能訪問這個加鎖的資源。互斥鎖的特點 多個執行緒訪問資源的時候是序列的 互斥鎖的使用步驟 建立乙個互斥鎖 pthread mutex t mutex 初始化這把鎖 pthread mutex init mutex,nu...

Go 互斥鎖和讀寫互斥鎖的實現

目錄 先來看這樣一段 所存在的問題 var wg sync.waitgroup var x int64 func main func f wg.done 這裡為什麼輸出是 12135 不同的機器結果不一樣 而不是20000。因為 x 的賦值,總共分為三個步驟 取出x的值 計算x的結果 給x賦值。那麼...

linux之mutex 互斥鎖

在posix thread中定義有一套專門用於執行緒同步的mutex函式 有兩種方法建立互斥鎖,靜態方式和動態方式。posix定義了乙個巨集pthread mutex initializer來靜態初始化互斥鎖,方法如下 pthread mutex t mutex pthread mutex init...