go:并发安全和锁 您所在的位置:网站首页 go语言的锁 go:并发安全和锁

go:并发安全和锁

2024-01-04 07:50| 来源: 网络整理| 查看: 265

0/参考网址

zhuanlan.zhihu.com/p/105994357

1/并发安全和锁 在某些场景中,可能会存在多个goroutine(协程)同时操作一个资源,这种情况会发生竞态问题,举个例子 package main import ( "fmt" "sync" ) // 多个goroutine并发操作全局变量x var x int64 var wg sync.WaitGroup func add() { for i := 0; i < 50; i++ { x = x + 1 } wg.Done() } func main() { wg.Add(2) go add() go add() wg.Wait() fmt.Println(x) } 以上代码中,两个goroutine去累加变量x,这两个goroutine在访问和修改x变量的时候就会存在数据竞争。因此就需要锁。 1.1/互斥锁 互斥锁是一种常用的控制共享资源访问的方法。 它能够保证同时(同一时间)只有一个goroutine可以访问共享资源。 Go语言中通过sync包中的Mutex类型来实现互锁。 sync.Mutex是一个结构体,值类型,给函数传参的时候需要传指针。 var ( x int64 wg sync.WaitGroup lock sync.Mutex // 互斥锁 ) // 修改了上面的func add()函数 func add() { for i := 0; i < 50; i++ { lock.Lock() // 加锁,这就相当于,此时此刻,该变量x只能自己使用,别人不能操作 x = x + 1 lock.Unlock() // 释放锁 } wg.Done() } 使用互斥锁能够保证同一时间有且只有一个goroutine进入临界区,其他的goroutine则在等待, 如果有多个goroutine等待,下一次将在这些goroutine中随机选择一个进入临界区。 1.2/读写互斥锁 互斥锁是完全互斥的,但是很多场景下是读多写少。 如果是并发地去读一个资源不涉及修改(写)的时候是没有必要加锁的。 读写锁在Go语言中使用sync包中的RWMutex类型。 package main import ( "fmt" "sync" "time" ) // 读写互斥锁 var ( x int64 wg sync.WaitGroup lock sync.Mutex // 互斥锁 rwLock sync.RWMutex // 读写互斥锁 ) // 函数,读变量 func read() { // lock.Lock() rwLock.Lock() time.Sleep(time.Millisecond) // lock.Unlock() rwLock.Unlock() wg.Done() } // 函数,写变量 func write() { // lock.Lock() rwLock.Lock() x = x + 1 time.Sleep(time.Millisecond * 10) // lock.Unlock() rwLock.Unlock() wg.Done() } func main() { start := time.Now() for i := 0; i < 1000; i++ { wg.Add(1) go read() } for i := 0; i < 10; i++ { wg.Add(1) go write() } wg.Wait() fmt.Println(time.Now().Sub(start)) } 需要注意的是读写锁非常适合读多写少的场景,如果读写的操作差别不大,读写锁的优势就发挥不出来了。


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有