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