并发安全和锁

  • 时间:
  • 浏览:
  • 来源:互联网

有时候在Go代码中可能会存在多个goroutine同时操作一个资源,这种情况会发生数据竞态问题。
举例:

var x int64
var wg sync.WaitGroup

func add() {
	for i := 0; i < 5000; i++ {
		x = x + 1
	}
	wg.Done()
}

func main() {
	wg.Add(2)
	go add()
	go add()
	wg.Wait()
	fmt.Println(x)
}

上面的代码中开启了 2 个goroutine去累加变量x的值,这 2 个goroutine在访问和修改x变量的时候存在数据竞争,导致最后的结果与期待的不符。

互斥锁

互斥锁是一种常用的控制共享资源访问的方法,它能够保证同时只有一个goroutine可以访问共享资源。Go语言使用sync包的Mutex类型来实现互斥锁。

var lock sync.Mutex

func add() {
	for i := 0; i < 5000; i++ {
		lock.Lock() //加锁
		x = x + 1
		lock.Unlock() //解锁
	}
	wg.Done()
}

使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待;多个goroutine同时等待一个锁时,唤醒的策略是随机的。

读写互斥锁

很多实际的场景下是读多写少,并发的去读取一个资源不涉及修改的时候没有必要加锁,这种场景下使用读写锁是更好的一种选择。读写锁在Go语言中使用sync包的RWMutex类型。

本文链接http://www.dzjqx.cn/news/show-617559.html