初学语言,用中文解释了一下,便于理解
```go
func TestCounter(t *testing.T) {
counter := 0
for i := 0; i < 5000; i++ { // 循环出 5000 个协程程序
go func() { //执行这个协程匿名函数给 counter 自增
counter++
}()
}
// 执行完成后得到的结果并不是 5000,这是因为这 5000 个并发协程都在抢用 counter,
// 这样的话,整个程序是不安全的,我们需要对 counter 的共享内存做锁的保护
time.Sleep(1 * time.Second)
t.Logf("counter = %d", counter)
}
func TestCounterThreadSafe(t *testing.T) {
var mut sync.Mutex // ⚠️ 1. 增加一个互斥锁
counter := 0
for i := 0; i < 5000; i++ {
go func() {
defer func() { // ⚠️ 3. 使用 defer 用于释放资源,此处用于解除锁
mut.Unlock()
}()
mut.Lock() // ⚠️ 2. counter 自增前加锁
counter++
}()
}
time.Sleep(1 * time.Second)
// 加这个延时是担心程序一下就跑完了,甚至协程还没有跑完,
// 给一个定时肯定不是万全之策,但是使用 waitGroup 就好办啦
t.Logf("counter = %d", counter)
}
func TestCounterThreadSafeWaitGroup(t *testing.T) {
var mut sync.Mutex
var wg sync.WaitGroup // 1.声明一个等待组
counter := 0
for i := 0; i < 5000; i++ {
wg.Add(1) // 3.每启动一个协程都新增加一个等待
go func() {
defer func() {
mut.Unlock()
}()
mut.Lock()
counter++
wg.Done() // 4.这个等待完成了
}()
}
wg.Wait()
// 2.这里等待上面所有的等待完成后马上走下面的程序
// 这样就可以准确的等待协程执行了
t.Logf("counter = %d", counter)
}
```
展开