官方黄金网站软件app大全下载,上海做网站的公司多少钱,北京网站优化前景,网站开发公司杭州网站建设✍个人博客#xff1a;Pandaconda-CSDN博客 #x1f4e3;专栏地址#xff1a;http://t.csdnimg.cn/UWz06 #x1f4da;专栏简介#xff1a;在这个专栏中#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话#xff0c;欢迎点赞#x1f44d;收藏… ✍个人博客Pandaconda-CSDN博客 专栏地址http://t.csdnimg.cn/UWz06 专栏简介在这个专栏中我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话欢迎点赞收藏您的支持就是我创作的最大动力 91. Go 写锁怎么实现
加写锁
const rwmutexMaxReaders 1 30
func (rw *RWMutex) Lock() {// First, resolve competition with other writers.rw.w.Lock()// Announce to readers there is a pending writer.r : atomic.AddInt32(rw.readerCount, -rwmutexMaxReaders) rwmutexMaxReaders// Wait for active readers.if r ! 0 atomic.AddInt32(rw.readerWait, r) ! 0 {runtime_Semacquire(rw.writerSem)}
}首先调用互斥锁的 lock获取到互斥锁之后如果计算之后当前仍然有其他 goroutine 持有读锁那么就调用 runtime_SemacquireMutex 休眠当前的 goroutine 等待所有的读操作完成
这里readerCount 原子性加上一个很大的负数是防止后面的协程能拿到读锁阻塞读
释放写锁
func (rw *RWMutex) Unlock() {// Announce to readers there is no active writer.r : atomic.AddInt32(rw.readerCount, rwmutexMaxReaders)// Unblock blocked readers, if any.for i : 0; i int(r); i {runtime_Semrelease(rw.readerSem, false)}// Allow other writers to proceed.rw.w.Unlock()
}解锁的操作会先调用 atomic.AddInt32(rw.readerCount, rwmutexMaxReaders) 将恢复之前写入的负数然后根据当前有多少个读操作在等待循环唤醒
92. Go 读写锁的注意事项以及区别
注意点
读锁或写锁在 Lock() 之前使用 Unlock() 会导致 panic 异常。使用 Lock() 加锁后再次 Lock() 会导致死锁不支持重入需 Unlock() 解锁后才能再加锁。锁定状态与 goroutine 没有关联一个 goroutine 可以 RLockLock另一个 goroutine 可以 RUnlockUnlock。
互斥锁和读写锁的区别
读写锁区分读者和写者而互斥锁不区分。互斥锁同一时间只允许一个线程访问该对象无论读写读写锁同一时间内只允许一个写者但是允许多个读者同时读对象。
93. Go 互斥锁是什么
Go sync 包提供了两种锁类型互斥锁 sync.Mutex 和读写互斥锁 sync.RWMutex都属于悲观锁。
概念
Mutex是互斥锁当一个 goroutine 获得了锁后其他 goroutine 不能获取锁只能存在一个写者或读者不能同时读和写
使用场景
多个线程同时访问临界区为保证数据的安全锁住一些共享资源以防止并发访问这些共享数据时可能导致的数据不一致问题。
获取锁的线程可以正常访问临界区未获取到锁的线程等待锁释放后可以尝试获取锁