并发编程
作者:互联网
Go 并发原语
并发问题出现的原因---> 在Go开发中如何监测到这个问题---> Go 是如何解决的
互斥锁
package main
import(
"fmt"
"sync"
)
func main(){
var count = 0
// 使用 WaitGroup等待 10个goroutine 完成
var wg sync.WaitGroup
wg.Add(10)
for i :=0;i< 10; i++{
go func () {
defer wg.Done()
// 对变量count 执行10次加1
for j:=0;j<100000; j++{
count++
}
}()
}
// 等10个goroutine 完成
wg.Wait()
fmt.Println(count)
}
出错原因
分析代码---> 这段代码一共启动了10个goroutine, 这10个goroutine 可能同时进行count++的操作
如何监测
Data Race Detector:https://go.dev/doc/articles/race_detector
groutine8 对内存地址0x00c00012c078 有度的操作 (go文件的第17行), 同时groutine7 对内存地址有写操作(go文件的第17行)
Data Race Deltector 只能在代码触发并发问题后才给予反馈
go tool compile -race -S .\testMutext.go
可以查看 go 编译后的代码,之前了解到, 产生并发问题是在 count++ 附近,重点关注一下
代码中增加了runtine.recefuncenter, runtime.recered, runtime.recewrite, runtime.recefuncexit等监测data race问题
如何解决
Go标准库中, package sync提供了锁相关的一系列同步原语,Mutex 实现了该包提供的一个 Locker的接口
type Locker interface {
Lock()
Unlock()
}
互斥锁Mutex 提供了两个方法 Lock和Unlock,进入临界区前调用Lock方法, 退出临界区的时候调用Unlock方法
func(m *Mutex)Lock()
func(m*Mutex)Unlock()
Mutex 嵌入到Struct中使用
type Counter struct{
mu sync.Mutex
Count unint64
}
使用Mutex解决并发锁问题的几种代码形式
1.
package main
import (
"fmt"
"sync"
)
func main(){
// 互斥锁保护计数器
var mu sync.Mutex
// 计数器的值
var count = 0
// 辅助变量,用来确认所有的goroutine 都完成
var wg sync.WaitGroup
wg.Add(10)
// 启动 10个gourontine
for i:=0; i<10; i++{
go func () {
defer wg.Done()
// 累加 10万次
for j:=0; j< 100000;j++{
mu.Lock()
count++
mu.Unlock()
}
}()
}
wg.Wait()
fmt.Println(count)
}
package main
import (
"fmt"
"sync"
)
func main() {
var counter Counter
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
for j := 0; j < 100000; j++ {
counter.Lock()
counter.Count++
counter.Unlock()
}
}()
}
wg.Wait()
fmt.Println(counter.Count)
}
type Counter struct{
sync.Mutex
Count uint64
}
package main
import(
"fmt"
"sync"
)
func main(){
//封装好的计数器
var counter Counter
var wg sync.WaitGroup
wg.Add(10)
//启动 10个goroutine
for i:=0;i<10;i++{
go func(){
defer wg.Done()
// 执行10万次 累加
for j:=0; j<100000;j++{
counter.Incr() //受到锁保护的方法
}
}()
}
wg.Wait()
fmt.Println(counter.Count())
}
// 线程安全的计数器类型
type Counter struct{
CounterType int
Name string
mu sync.Mutex
count uint64
}
// 加1 的方法,内部使用互斥锁保护
func (c *Counter) Incr(){
c.mu.Lock()
c.count++
c.mu.Unlock()
}
// 得到计数器的值,也需要锁保护
func (c *Counter) Count() uint64{
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}
标签:wg,10,编程,sync,var,并发,Mutex,go 来源: https://www.cnblogs.com/stormliu/p/16283044.html