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之间传递数据:共享变量, 通过信道 // 如果是修改共享变量,建议加锁 //如果是协程之间通信,用信道