28 goroutine互斥锁

互斥锁

互斥锁是传统并发编程中对共享资源进行访问控制的主要手段,它由标准库sync中的Mutex结构体类型表示。sync.Mutex类型只有两个公开的指针方法,Lock和Unlock。Lock锁定当前的共享资源,Unlock进行解锁。

  • demo

在使用前通过Lock上锁,使用后能过Unlock解锁。

var count = 0
var wg sync.WaitGroup
var mutex sync.Mutex

func test() {
    mutex.Lock()
    count++
    fmt.Println("the count is:", count)
    time.Sleep(time.Millisecond*2)
    mutex.Unlock()
    wg.Done()
}

func main() {
    for r := 0; r < 20; r++ {
        wg.Add(1)
        go test()
    }
    wg.Wait()
}
  • 通过-race build查看资源竞争,再执行exe对比
go build -race main.go
main.exe

发现未加锁之前有报错,协程之间存在竞争关系

  • demo2

可以关闭下面的互斥锁后,观察它们的变化

var count = 0
var wg sync.WaitGroup
var mutex sync.Mutex

var m = make(map[int]int, 0)

func test(num int) {
    mutex.Lock()
    var sum int = 1
    for i := 1; i <= num; i++ {
        sum *= i
    }
    m[num] = sum
    fmt.Printf("key=%v value=%v\n", num, sum)
    time.Sleep(time.Millisecond * 2)
    mutex.Unlock()
    wg.Done()
}

func main() {
    for r := 0; r < 40; r++ {
        wg.Add(1)
        go test(r)
    }
    wg.Wait()
}
读写互斥锁

读取的时候,可以并发地访问;但写得时候,同一时刻只允许一人操作。

也就是说,当一个goruntine进行写操作时,其他goruntine既不能进行读操作,也不能进行写操作。

Go中的读写锁由结构体类型sync.RWMutex表示。它包含了两对方法:一组是对写操作的锁定和解锁,简称“写锁定”和“写解锁”

func (*RWMutex) Lock()
func (*RWMutex) Unlock()

另一组表示对读操作的锁定和解锁,简称“读锁定”与“读解锁”

func (*RWMutex) RLock()
func (*RWMutex) RUnlock()
  • 写操作时互斥,读操作时并行
var count = 0
var wg sync.WaitGroup
var mutex sync.RWMutex

var m = make(map[int]int, 0)

func write(){
    mutex.Lock()
    fmt.Println("执行写操作")
    time.Sleep(time.Second * 2)
    mutex.Unlock()
    wg.Done()
}

func read(){
    mutex.RLock()
    fmt.Println("执行读操作---")
    //time.Sleep(time.Millisecond * 50)
    mutex.RUnlock()
    wg.Done()
}

func main() {
    //开启10个协程执行读操作
    for i := 0; i < 10; i++{
        wg.Add(1)
        go write()
    }
    //开启10个协程执行写操作
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go read()
    }
    wg.Wait()
}
执行写操作
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行读操作---
//执行写操作
//执行写操作
//……

你可能感兴趣的:(28 goroutine互斥锁)