一架梯子,一头程序猿,仰望星空!

golang Mutex和RWMutex


本章介绍go语言内置的加锁机制。

  • Mutex - 互斥锁
  • RWMutex - 读写互斥锁

1.Mutex

Mutex是一个互斥锁,可以作为为其他结构体的字段,零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。

基本用法:

// 初始化Mutex对象
lk := sync.Mutex{}
// 加锁
lk.Lock()
	
// 处理业务逻辑
	
// 解锁
lk.Unlock()

例子:

package main

import (
	"fmt"
	"sync"
)

var count int = 0

func main() {
	// 初始化锁
	lk := sync.Mutex{}

	done := make(chan bool)

	for i:=0; i < 100; i++ {
	    // 并发的累加count
		go func() {
			// 加锁
			lk.Lock()
			// 延迟解锁
			defer lk.Unlock()

			// 处理业务逻辑
			count++
			done <- true
		}()
	}

	for i:=0; i < 100; i++ {
		<-done
	}
	fmt.Println(count)
}

2.RWMutex

RWMutex是读写互斥锁。该锁可以被同时多个读取者持有或唯一个写入者持有。RWMutex可以创建为其他结构体的字段;零值为解锁状态。RWMutex类型的锁也和线程无关,可以由不同的线程加读取锁/写入和解读取锁/写入锁。

基本用法:

// 初始化RWMutex对象
lk := sync.RWMutex{}
// 加写锁
lk.Lock()
	
// 处理业务逻辑
	
// 解除写锁
lk.Unlock()

// 加读锁
lk.RLock()

// 处理业务逻辑

// 解除读锁
lk.RUnlock

跟Mutex的区别就是锁的粒度更小了,区分为读锁和写锁,读写锁的互斥关系如下:

协程1协程2阻塞状态
读锁读锁不阻塞
读锁写锁阻塞
写锁写锁阻塞

大家都加读锁的时候是不会阻塞的,其他情况就会议阻塞协程。