网站首页做跳转,海南 网站开发,潍坊网站建设SEO优化,电商网站可以用dw做文章目录背景RWMutex 简介代码验证多个协程请求读锁 RLock() 和 RLock()读写交错 RLock() 和 Lock()写入的时候读取读取的时候写入请求多个写Lock() 和 Lock()背景
Mutex 互斥锁是严格锁定读和写#xff0c;如果我们需要单独对读或者写添加锁需要使用 sync包的RWMutex 针对读…
文章目录背景RWMutex 简介代码验证多个协程请求读锁 RLock() 和 RLock()读写交错 RLock() 和 Lock()写入的时候读取读取的时候写入请求多个写Lock() 和 Lock()背景
Mutex 互斥锁是严格锁定读和写如果我们需要单独对读或者写添加锁需要使用 sync包的RWMutex 针对读多写少的情况
读写锁的原则是 1、可以随便读多个协程同时读。 2、写的时候不能读也不能写。
RWMutex 简介
RWMutex 类型一共有 6 个方法
RLock/RUnlockRLock 锁定读操作如果锁已被写操作持有RLock 方法会被阻塞直到锁释放如果锁已被读操作持有则无限制可以读取内容。RUnlock 是读操作对应的释放锁的方法。
Lock/UnlockLock 锁定读写操作不管是读操作持有锁还是写操作持有锁Lock 方法都会被阻塞直到锁释放。Unlock 是对应的释放锁方法。一般用于写操作的场景。
rUnlockSlow检查读操作是否全部释放锁如果读锁全部释放才可以唤醒写操作去请求写锁。
RLockerRLocker 为读操作返回一个 Locker 接口它的 Lock 方法会调用 RWMutex 类型的 RLock方法它的 Unlock 方法会调用 RWMutex 类型的 RUnlock方法。
其中 RLock() 和 RLock() 之间并不互斥可以共享锁Lock() 和 Lock() 之间还有 RLock() 和 Lock() 之间是互斥的.
代码验证
多个协程请求读锁 RLock() 和 RLock() package mainimport (fmttimesync
)// 声明Mutex变量
var mu *sync.RWMutex
var count 0
func main() {mu new(sync.RWMutex)for i: 0; i 1000; i {go readLock(i)}time.Sleep(2*time.Second)
}func readLock(i int) {mu.RLock()countfmt.Println(i, Read Lock is, count)mu.RUnlock()
}如上代码所示 我们启动1000个协程每个协程执行的readLock 中都添加了 RLock(). 执行结果如下
结果发现count 数字打印杂乱无章说明这些协程同时持有锁多个RLock() 之间并不互斥。
读写交错 RLock() 和 Lock()
写入的时候读取 package mainimport (fmttimesync
)// 声明Mutex变量
var mu *sync.RWMutex
var count 0
func main() {mu new(sync.RWMutex)for i : 0; i 5; i {go readLock(1)}for i : 0; i 5; i {go writLock(1)}time.Sleep(30*time.Second)
}func writLock(i int){mu.Lock()fmt.Println(i, Writ Lock start, count)countfmt.Println(i, Writ Lock is, count)time.Sleep(1 *time.Second)fmt.Println(i, Writ Lock done, count)mu.Unlock()
}func readLock(i int) {mu.RLock()fmt.Println(i, Read Lock is, count)// time.Sleep(10 *time.Second)fmt.Println(i, Read Lock done)mu.RUnlock()
}
Lock() 写入的时候sleep 期间 使用 RLock() 读取 结果如下 发现在 write 等待的时候 read 并没有获得锁 说明 Lock() 锁未释放 RLock() 不能获得锁
读取的时候写入 package mainimport (fmttimesync
)// 声明Mutex变量
var mu *sync.RWMutex
var count 0
func main() {mu new(sync.RWMutex)for i : 0; i 10; i {go readLock(1)}for i : 0; i 10; i {go writLock(1)}time.Sleep(15*time.Second)
}func writLock(i int){mu.Lock()fmt.Println(i, Writ Lock start, count)countfmt.Println(i, Writ Lock is, count)// time.Sleep(1 *time.Second)fmt.Println(i, Writ Lock done, count)mu.Unlock()
}func readLock(i int) {mu.RLock()fmt.Println(i, Read Lock is, count)time.Sleep(10 *time.Second)fmt.Println(i, Read Lock done)mu.RUnlock()
}在 RLock() sleep 期间 使用 Lock() 结果如下 read 期间 writ 并没有获得锁。 证明了 RLock() 和 Lock() 是互斥的。
请求多个写Lock() 和 Lock() package mainimport (fmttimesync
)// 声明Mutex变量
var mu *sync.RWMutex
var count 0
func main() {mu new(sync.RWMutex)for i: 0; i 1000; i {go writLock(i)}time.Sleep(2*time.Second)
}func writLock(i int){mu.Lock()countfmt.Println(i, Writ Lock is, count)mu.Unlock()
}启动1000个线程 使用 Lock() 执行 count , 结果如下 发现最红结果是1000并且是按照顺序进行计算的。 说明多个协程之间的Lock() 是互斥的。