mutex&chan 迈不过友情╰ 2022-06-09 10:00 147阅读 0赞 保证同步访问共享资源的安全访问,消除竞争状态的方式有三种: 原子函数、互斥锁、通道 无缓冲通道: 当一个goroutine向通道发送,此时没有goroutine接收时,会导致发送goroutine阻塞,只有通道被接收后。两个goroutine才被释放出来,可以去处理各自的工作。任意一个操作都无法离开另一个操作单独存在。 ### 互斥锁 ### 互斥锁用于在代码上创建一个临界区,保证同一时间只有一个goroutine可以执行这个临界区代码。 package main import ( "fmt" "runtime" "sync" ) var ( counter int wg sync.WaitGroup mutex sync.Mutex ) func main() { wg.Add(2) //表示要等待2个goroutine go incCounter(1) go incCounter(2) wg.Wait() //等待goroutine结束 fmt.Printf("Final Counter:%d\n", counter) } func incCounter(id int) { defer wg.Done() //在函数退出时,调用Done来通知main函数工作已经完成,goroutine结束 for count := 0; count < 2; count++ { mutex.Lock() //加锁,创建临界区 value := counter runtime.Gosched() value++ counter = value mutex.Unlock() //解锁 } } output: Finale Counter:4 ### 无缓冲通道 ### 在网球比赛中,两位选手会把球在两个人之间来回传递。选手总是处在以下两种状态之一:要么在等待接球,要么将球打向对方。使用两个goroutine来模拟网球比赛中的两个人,使用无缓冲通道来模拟球的来回。 当一方接球失败,关闭通道。另一方收到通道关闭,则说明自己won package main import ( "fmt" "math/rand" "sync" "time" ) var wg sync.WaitGroup //init函数在main函数之前运行 func init() { /* 初始化随机数种子,默认随机数种子为Seed(1),对程序而言属于产生伪随机数。 即当程序每次重新开始运行,结果都一致。 选定不同的随机种子,每次运行产生不一样的随机数。 */ rand.Seed(time.Now().UnixNano()) } func main() { court := make(chan int) //无缓存通道,模拟网球 wg.Add(2) //等待两个goroutine go player("Vera", court) //选手Vera go player("hannah", court) //选手Hannah court <- 1 //发球 wg.Wait() //等待游戏结束 } func player(name string, court chan int) { defer wg.Done() //函数退出时通知main函数goroutine已结束 for { ball, ok := <-court //等待球被打过来,接球 if !ok { //接收到通道关闭,则赢了 fmt.Printf("player %s won\n", name) return } //选择随机数,利用这个数来判断是否球是否接到 n := rand.Intn(100) if n%13 == 0 { //没接到球 fmt.Printf("player %s Missed\n", name) close(court) //关闭通道,游戏结束 return } //接到球,继续打 fmt.Printf("player %s Hit %d\n", name, ball) ball++ court <- ball //将球打向对方 } } output: player hannah Hit 1 player Vera Hit 2 player hannah Hit 3 player Vera Hit 4 player hannah Missed player Vera won
还没有评论,来说两句吧...