Golang 中的 RLock() 和 Lock() 之间有什么区别,以及当我们使用互斥锁时如何有效地使用它们?
nig*_*204 28
Lock():通过获取锁,一次只有一个 goroutine 读/写。
RLock():多个goroutine可以通过获取锁一次读取(不写入)。
package main
import (
"fmt"
"sync"
"time"
)
func main() {
a := 0
lock := sync.RWMutex{}
for i := 1; i < 10; i++ {
go func(i int) {
lock.Lock()
fmt.Printf("Lock: from go routine %d: a = %d\n",i, a)
time.Sleep(time.Second)
lock.Unlock()
}(i)
}
b := 0
for i := 11; i < 20; i++ {
go func(i int) {
lock.RLock()
fmt.Printf("RLock: from go routine %d: b = %d\n",i, b)
time.Sleep(time.Second)
lock.RUnlock()
}(i)
}
<-time.After(time.Second*10)
}
Run Code Online (Sandbox Code Playgroud)
1) 当一个 go-routine 已经获得了一个 RLock() 时,另一个 go-routine 是否可以获取一个 Lock() 进行写入,或者它必须等到 RUnlock() 发生?
2) 当有人已经为 map 获取了 Lock() 时会发生什么,其他 go-routine 是否仍然可以获取 RLock()
3) 假设我们在这里处理 Maps,是否有可能出现“并发读/写 Map”错误?
有关更多说明,请参见以下示例:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
lock := sync.RWMutex{}
b := map[string]int{}
b["0"] = 0
go func(i int) {
lock.RLock()
fmt.Printf("RLock: from go routine %d: b = %d\n",i, b["0"])
time.Sleep(time.Second*3)
fmt.Printf("RLock: from go routine %d: lock released\n",i)
lock.RUnlock()
}(1)
go func(i int) {
lock.Lock()
b["2"] = i
fmt.Printf("Lock: from go routine %d: b = %d\n",i, b["2"])
time.Sleep(time.Second*3)
fmt.Printf("Lock: from go routine %d: lock released\n",i)
lock.Unlock()
}(2)
<-time.After(time.Second*8)
fmt.Println("*************************************8")
go func(i int) {
lock.Lock()
b["3"] = i
fmt.Printf("Lock: from go routine %d: b = %d\n",i, b["3"])
time.Sleep(time.Second*3)
fmt.Printf("Lock: from go routine %d: lock released\n",i)
lock.Unlock()
}(3)
go func(i int) {
lock.RLock()
fmt.Printf("RLock: from go routine %d: b = %d\n",i, b["3"])
time.Sleep(time.Second*3)
fmt.Printf("RLock: from go routine %d: lock released\n",i)
lock.RUnlock()
}(4)
<-time.After(time.Second*8)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10487 次 |
| 最近记录: |