Golang的包sync實現了兩種類型的鎖: sync.Mutex 和 sync.RWMutex。通過閱讀源代碼我們可以知道sync.RWMutex是基於sync.Mutex實現的,其中的只讀鎖的實現使用類似引用計數的方式。
對於任意 sync.Mutex 或 sync.RWMutex 變量l。 如果 n < m ,那么第n次 l.Unlock() 調用在第 m次 l.Lock()調用返回前發生。
比如例子:
package main
import (
"sync"
)
var l sync.Mutex
var a string
func f() {
a = "hello, world"
l.Unlock()
}
func main() {
l.Lock()
go f()
l.Lock()
print(a)
}
這個例子會輸出 hello,world 的。
因為,第一次 l.Unlock() 調用(在f函數中)在第二次 l.Lock() 調用(在main 函數中)返回之前發生,也就是在 print 函數調用之前發生。
比如如果代碼修改成下面方式,
package main
import (
"sync"
)
var l sync.Mutex
var a string
func f() {
a = "hello, world"
print("21,")
l.Unlock()
print("22,")
}
func main() {
l.Lock()
print("1,")
f()
print("2,")
l.Lock()
print("3,")
print(a)
}
執行結果是:1,21,22,2,3,hello, world
如果代碼改成下面方式
package main
import (
"sync"
)
var l sync.Mutex
var a string
func f() {
a = "hello, world"
print("21,")
l.Unlock()
print("22,")
}
func main() {
l.Lock()
print("1,")
go f()
print("2,")
l.Lock()
print("3,")
print(a)
}
執行結果是:1,2,21,22,3,hello, world
下面代碼來自:https://github.com/astaxie/beego/blob/master/safemap.go 用讀寫鎖實現了 安全的map
package beego
import (
"sync"
)
type BeeMap struct {
lock *sync.RWMutex
bm map[interface{}]interface{}
}
func NewBeeMap() *BeeMap {
return &BeeMap{
lock: new(sync.RWMutex),
bm: make(map[interface{}]interface{}),
}
}
//Get from maps return the k's value
func (m *BeeMap) Get(k interface{}) interface{} {
m.lock.RLock()
defer m.lock.RUnlock()
if val, ok := m.bm[k]; ok {
return val
}
return nil
}
// Maps the given key and value. Returns false
// if the key is already in the map and changes nothing.
func (m *BeeMap) Set(k interface{}, v interface{}) bool {
m.lock.Lock()
defer m.lock.Unlock()
if val, ok := m.bm[k]; !ok {
m.bm[k] = v
} else if val != v {
m.bm[k] = v
} else {
returnfalse
}
return true
}
// Returns true if k is exist in the map.
func (m *BeeMap) Check(k interface{}) bool {
m.lock.RLock()
defer m.lock.RUnlock()
if _, ok := m.bm[k]; !ok {
returnfalse
}
return true
}
func (m *BeeMap) Delete(k interface{}) {
m.lock.Lock()
defer m.lock.Unlock()
delete(m.bm, k)
}
參考資料:
go_mem 內存模型
https://code.google.com/p/golang-china/wiki/go_mem
http://hugozhu.myalert.info/2013/04/20/31-golang-memory-model.html
Golang讀寫鎖的實現源碼
http://golang.org/src/pkg/sync/rwmutex.go
用讀寫鎖實現的線程安全的Map
https://github.com/astaxie/beego/blob/master/safemap.go