【博客302】Go的互斥锁的使用

内容: 当多个协程去操作同一数据块的时候,会产生竞争关系。此时需要上锁来保证数据的正确性

互斥锁接口:

mutex.Lock()
mutex.Unlock()

让四个go协程去对同一个变量进行++,各10次,最终正确结果应该是40:

一、没有互斥锁的竞争例子:

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var (
	counter int
	wg sync.WaitGroup
	mutex sync.Mutex
)

func main() {
	wg.Add(4)

	go incCounter(1)
	go incCounter(2)
	go incCounter(3)
	go incCounter(4)

	fmt.Println("Waiting To Finish")
	wg.Wait()

	fmt.Println("Final Counter:", counter)
}

func incCounter(id int) {
	defer wg.Done()
	for count := 0; count < 10; count++ {

		{
			//模拟CPU处理时取完变量的值,但此时时间片到了,让出CPU;
			//等获得CPU时再++然后写回,此时会覆盖其它协程++的结果
			value := counter
			runtime.Gosched()
			value++
			counter = value
		}
	}
}

结果:

GOPATH=/home/luzejia/Workspace/Go #gosetup
/usr/local/go/bin/go build -o /tmp/___go_build_study_35_go /home/luzejia/Workspace/Go/go_study/src/study_35.go #gosetup
/tmp/___go_build_study_35_go #gosetup
Waiting To Finish
Final Counter: 10

Process finished with exit code 0		

分析:

CPU处理时取完变量的值,但此时时间片到了,让出CPU;
等获得CPU时再++然后写回,此时会覆盖其它协程++的结果

二、有互斥锁时的没有竞争例子:

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var (
	counter int
	wg sync.WaitGroup
	mutex sync.Mutex
)

func main() {
	wg.Add(4)

	go incCounter(1)
	go incCounter(2)
	go incCounter(3)
	go incCounter(4)

	fmt.Println("Waiting To Finish")
	wg.Wait()

	fmt.Println("Final Counter:", counter)
}

func incCounter(id int) {
	defer wg.Done()
	for count := 0; count < 10; count++ {
		mutex.Lock()
		{
			//模拟CPU处理时取完变量的值,但此时时间片到了,让出CPU;
			//等获得CPU时再++然后写回,此时会覆盖其它协程++的结果
			value := counter
			runtime.Gosched()
			value++
			counter = value
		}
		mutex.Unlock()
	}
}

结果:

GOPATH=/home/luzejia/Workspace/Go #gosetup
/usr/local/go/bin/go build -o /tmp/___go_build_study_35_go /home/luzejia/Workspace/Go/go_study/src/study_35.go #gosetup
/tmp/___go_build_study_35_go #gosetup
Waiting To Finish
Final Counter: 40

Process finished with exit code 0

分析:

有了互斥锁,使得对变量的++变成了原子操作,所以不会出现混乱的竞争关系从而导致错误结果

大四学生一枚,如果文章有错误的地方,欢迎在下方提出,每条评论我都会去认真看并回复,同时感谢指正的前辈。有喜欢C/C++,linux的同学欢迎私信一起讨论学习。

你可能感兴趣的:(【博客302】Go的互斥锁的使用)