Mutex

Mutex

Mutex 用于提供一种加锁机制(Locking Mechanism),可确保在某时刻只有一个协程在临界区运行,以防止出现竞态条件。

Mutex 可以在 [sync] 包内找到。[Mutex] 定义了两个方法:[Lock]和 [Unlock](。所有在 Lock 和 Unlock 之间的代码,都只能由一个 Go 协程执行,于是就可以避免竞态条件。

1
2
3
mutex.Lock()  
x = x + 1  
mutex.Unlock()
在上面的代码中,x = x + 1 只能由一个 Go 协程执行,因此避免了竞态条件。

如果有一个 Go 协程已经持有了锁(Lock),当其他协程试图获得该锁时,这些协程会被阻塞,直到 Mutex 解除锁定为止。

 

使用Mutex

package main

import (
    "fmt"
    "sync"
)

// 使用锁的场景:多个goroutine通过共享内存在实现数据通信
// 临界区:当程序并发地运行时,多个 [Go 协程]同时修改共享资源的代码。这些修改共享资源的代码称为临界区。

//如果在任意时刻只允许一个 Go 协程访问临界区,那么就可以避免竞态条件。而使用 Mutex 可以达到这个目的


//var x  = 0  //全局,各个goroutine都可以拿到并且操作
//func increment(wg *sync.WaitGroup,m *sync.Mutex) {
//    m.Lock()
//    x = x + 1
//    m.Unlock()
//    wg.Done()
//}
//func main() {
//    var w sync.WaitGroup
//    var m sync.Mutex  //是个值类型,函数传递需要传地址
//    fmt.Println(m)
//    for i := 0; i < 1000; i++ {
//        w.Add(1)
//        go increment(&w,&m)
//    }
//    w.Wait()
//    fmt.Println("final value of x", x)
//}

// 通过信道来做
var x  = 0
func increment(wg *sync.WaitGroup, ch chan bool) {
    ch <- true  // 缓冲信道放满了,就会阻塞
    x = x + 1
    <- ch
    wg.Done()
}
func main() {
    var w sync.WaitGroup
    ch := make(chan bool, 1)  //定义了一个有缓存大小为1的信道
    for i := 0; i < 1000; i++ {
        w.Add(1)
        go increment(&w, ch)
    }
    w.Wait()
    fmt.Println("final value of x", x)
}


// 不同goroutine之间传递数据:共享变量,  通过信道
// 如果是修改共享变量,建议加锁
//如果是协程之间通信,用信道

 

posted @ 2021-06-15 19:10  Palpitate~  阅读(31)  评论(0编辑  收藏  举报