您的位置:首页 > 编程语言

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中读写锁中的读锁是可重入共享锁,写锁是互斥锁,读锁不能晋升为写锁。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: