前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Go语言互斥锁和读写锁

Go语言互斥锁和读写锁

原创
作者头像
IT工作者
发布2022-03-31 11:53:56
发布2022-03-31 11:53:56
73300
代码可运行
举报
文章被收录于专栏:程序技术知识程序技术知识
运行总次数:0
代码可运行

一、互斥锁

  • Go语言中多个协程操作一个变量时会出现冲突的问题
  • go run -race 可以查看竞争
  • 可以使用sync.Mutex对内容加锁
  • 互斥锁的使用场景
  • 多个goroutine访问同一个函数(代码段)
  • 这个函数操作一个全局变量
  • 为了保证共享变量安全性,值合法性
  • 使用互斥锁模拟售票窗口
代码语言:javascript
代码运行次数:0
运行
复制
package main

import (
   "fmt"
   "sync"
   "time"
   "math/rand"
)

var (
   //票数
   num = 100
   wg  sync.WaitGroup
   //互斥锁
   mu sync.Mutex
)

func sellTicker(i int) {
   defer wg.Done()
   for {
      //加锁,多个goroutine互斥
      mu.Lock()
      if num >= 1 {
         fmt.Println("第", i, "个窗口卖了", num)
         num = num - 1
      }
      //解锁
      mu.Unlock()

      if num <= 0 {
         break
      }
      //添加休眠,防止结果可能出现在一个goroutine中
      time.Sleep(time.Duration(rand.Int63n(1000) * 1e6))
   }

}

func main() {
   //设置随机数种子
   rand.Seed(time.Now().UnixNano())
   //计算器的起始值和票数相同
   wg.Add(4)
   go sellTicker(1)
   go sellTicker(2)
   go sellTicker(3)
   go sellTicker(4)
   wg.Wait()

   fmt.Println("所有票卖完")
}

二、RWMutex读写锁

RWMutex 源码如下

代码语言:javascript
代码运行次数:0
运行
复制
// There is a modified copy of this file in runtime/rwmutex.go.
// If you make any changes here, see if you should make them there.

// A RWMutex is a reader/writer mutual exclusion lock.
// The lock can be held by an arbitrary number of readers or a single writer.
// The zero value for a RWMutex is an unlocked mutex.
//
// A RWMutex must not be copied after first use.
//
// If a goroutine holds a RWMutex for reading and another goroutine might
// call Lock, no goroutine should expect to be able to acquire a read lock
// until the initial read lock is released. In particular, this prohibits
// recursive read locking. This is to ensure that the lock eventually becomes
// available; a blocked Lock call excludes new readers from acquiring the
// lock.
type RWMutex struct {
    w           Mutex  // held if there are pending writers
    writerSem   uint32 // semaphore for writers to wait for completing readers
    readerSem   uint32 // semaphore for readers to wait for completing writers
    readerCount int32  // number of pending readers
    readerWait  int32  // number of departing readers
}

Go语言标准库中API如下

代码语言:javascript
代码运行次数:0
运行
复制
type RWMutex
  func (rw *RWMutex) Lock()//禁止其他协程读写
  func (rw *RWMutex) Unlock()
  func (rw *RWMutex) RLock()//禁止其他协程写入,只能读取
  func (rw *RWMutex) RUnlock()
  func (rw *RWMutex) RLocker() Locke

  • Go语言中的map不是线程安全的,多个goroutine同时操作会出现错误.
  • RWMutex可以添加多个读锁或一个写锁.读写锁不能同时存在.
  • map在并发下读写就需要结合读写锁完成
  • 互斥锁表示锁的代码同一时间只能有一个人goroutine运行,而读写锁表示在锁范围内数据的读写操作
代码语言:javascript
代码运行次数:0
运行
复制
package main

import (
   "fmt"
   "sync"
   "strconv"
)

func main() {
   var rwm sync.RWMutex
   m := make(map[string]string)
   var wg sync.WaitGroup
   wg.Add(10)
   for i := 0; i < 10; i++ {
      go func(j int) {
         //没有锁在map时可能出现问题
         rwm.Lock()
         m["key"+strconv.Itoa(j)] = "value" + strconv.Itoa(j)
         fmt.Println(m)
         rwm.Unlock()
         wg.Done()
      }(i)
   }
   wg.Wait()
   fmt.Println("程序结束")
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档