Go并发编程之美-读写锁
2019-02-13 08:00
120 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37055174/article/details/99956618
一、前言
go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中读写锁
二、读写锁
go中读写锁,在没有线程获取写锁情况下多个线程可以同时获取读锁,读锁是可重入锁,写锁则是互斥锁(不可重入)。
package main import ( "fmt" "sync" "time" ) var ( counter int //计数器 wg sync.WaitGroup //信号量 lock sync.RWMutex //读写锁 ) func main() { //1.两个信号 wg.Add(1) //2.获取读锁 fmt.Println("main thread wait rlock") lock.RLock() fmt.Println("main thread got rlock") //3.开启子线程 go incCounter() fmt.Println(counter) time.Sleep(time.Second * 5) //4.释放读锁 lock.RUnlock() fmt.Println("main thread release rlock") //5.等待子线程结束 wg.Wait() fmt.Println(counter) } func incCounter() { defer wg.Done() //2.1.获取锁 fmt.Println("sub thread wait rlock") lock.Lock() fmt.Println("sub thread got rlock") //2.2.计数加1 counter++ //2.3.释放独占锁 lock.Unlock() fmt.Println("sub thread relese rlock") }
- [p]如上代码go中使用sync.RWMutex可以获取一个开箱即用的读写锁
代码(2)主线程使用lock.RLock()获取读锁,然后开启了子线程(代码3),然后在主线程持有读锁的情况下休眠了5s后释放了锁。
子线程在代码2.1尝试使用 lock.Lock()获取写锁,由于主线程还没释放读锁,所以子线程阻塞到了这里,直到主线程休眠后执行代码4释放了读锁。
执行代码会输出:
main thread wait rlock main thread got rlock 0 sub thread wait rlock main thread release rlock sub thread got rlock sub thread relese rlock 1这个例子说明了,当有线程获取了读锁并没释放时候,获取写锁的线程要等待。另外使用下面方法可以验证读锁是可重入锁:
lock.RLock() lock.RLock() fmt.Println(counter) lock.RUnlock() lock.RUnlock()使用下面代码可以验证同一个线程的读锁,不能晋升为写锁:
lock.RLock() lock.Lock() fmt.Println(counter) lock.Unlock() lock.RUnlock()上面代码执行会报错: [/p]
三、总结
go中读写锁中的读锁是可重入共享锁,写锁是互斥锁,读锁不能晋升为写锁。
相关文章推荐
- Go并发编程实践
- 再谈CERL:详论Go与Erlang的并发编程模型差异
- Go语言并发模型的2种编程方案
- Go并发编程实践
- Go基础编程:并发编程—channel
- Go并发编程之同步
- 【Java并发编程实战】– 使用读写锁实现同步数据访问 lock_2
- Go并发编程实践
- go基本语法学习笔记之并发编程
- java并发编程--互斥锁, 读写锁及条件
- 21 go并发编程-下
- 10 go并发编程-上
- Go 并发编程基础(一)goroutine,channel
- go语言学习-并发编程
- java并发编程--互斥锁, 读写锁及条件
- Java多线程并发编程之显示锁ReentrantLock和读写锁
- Go语言并发编程
- 可视化学习Go并发编程
- Go并发编程实战 第2版.pdf
- 可视化学习Go并发编程