Golang 中的有两种锁,为 sync.Mutex
和 sync.RWMutex
。
sync.Mutex
的锁只有一种锁:Lock()
,它是绝对锁,也称互斥锁,同一时间只能有一个锁。sync.RWMutex
叫读写锁,它有两种锁:RLock()
和Lock()
:RLock()
叫读锁。它不是绝对锁,可以有多个读者同时获取此锁(调用mu.RLock
)。Lock()
叫写锁,它是个绝对锁,就是说,如果一旦某人拿到了这个锁,别人就不能再获取此锁了
1 Mutex是互斥锁
2 RWMutex是读写锁,读写锁可以让多个读操作同时并发,同时读取,但是对于写操作是完全互斥的。也就是说,当一个goroutine进行写操作的时候,其他goroutine既不能进行读操作,也不能进行写操作。
var count int var wg sync.WaitGroup var rw sync.RWMutex func main() { wg.Add(10) for i:=0;i<5;i++ { go read(i) } for i:=0;i<5;i++ { go write(i); } wg.Wait() } func read(n int) { // 读锁是RLock(), rw.RLock() fmt.Printf("读goroutine %d 正在读取... ",n) v := count fmt.Printf("读goroutine %d 读取结束,值为:%d ", n,v) wg.Done() rw.RUnlock() } func write(n int) { // 写锁是Lock() rw.Lock() fmt.Printf("写goroutine %d 正在写入... ",n) v := rand.Intn(1000) count = v fmt.Printf("写goroutine %d 写入结束,新值为:%d ", n,v) wg.Done() rw.Unlock() }
map由于是非线程安全的,可以自己通过对map对象加锁来实现线程安全,具体操作是给新构造的map对象添加增删改查的方法,其中除了查添加读锁,其余的都是写锁,进而实现了线程安全,
// 安全的Map type SynchronizedMap struct { rw *sync.RWMutex data map[interface{}]interface{} } // 存储操作 func (sm *SynchronizedMap) Put(k,v interface{}){ sm.rw.Lock() defer sm.rw.Unlock() sm.data[k]=v } // 获取操作 只有这个加的是读锁, func (sm *SynchronizedMap) Get(k interface{}) interface{}{ sm.rw.RLock() defer sm.rw.RUnlock() return sm.data[k] } // 删除操作 func (sm *SynchronizedMap) Delete(k interface{}) { sm.rw.Lock() defer sm.rw.Unlock() delete(sm.data,k) } // 遍历Map,并且把遍历的值给回调函数,可以让调用者控制做任何事情 func (sm *SynchronizedMap) Each(cb func (interface{},interface{})){ sm.rw.RLock() defer sm.rw.RUnlock() for k, v := range sm.data { cb(k,v) } } // 生成初始化一个SynchronizedMap func NewSynchronizedMap() *SynchronizedMap{ return &SynchronizedMap{ rw:new(sync.RWMutex), data:make(map[interface{}]interface{}), } }