go-锁机制


本文摘自网络,作者,侵删。

Golang中的锁机制主要包含互斥锁和读写锁

互斥锁

互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁( lock )和解锁( unlock )。

func mutex() { 
var mu
sync.Mutex mu.Lock() 
fmt.Println("locked")
mu.Unlock() 
}

defer实现

func mutex() {
var mu 
sync.Mutex mu.Lock() 
defer mu.Unlock() 
fmt.Println("locked")
 }

【互斥锁的特点】:

  1. 原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量;

  2. 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量;

  3. 非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。

  4. 互斥锁是开箱即用的,只需要申明sync.Mutex即可直接使用

  5. 互斥锁应该是成对出现,在同步语句不可以再对锁加锁,看下面的示例:

func mutex() { 
var mu 
sync.Mutex mu.Lock() 
fmt.Println("parent locked") 
mu.Lock() 
fmt.Println("sub locked") 
mu.Unlock() 
mu.Unlock()
}

此时则会出现fatal error: all goroutines are asleep - deadlock!错误

读写锁

读写锁和互斥锁不同之处在于,可以分别针对读操作和写操作进行分别锁定,这样对于性能有一定的提升。 读写锁,对于多个写操作,以及写操作和读操作之前都是互斥的这一点基本等同于互斥锁。 但是对于同时多个读操作之前却非互斥关系,这也是相读写锁性能高于互斥锁的主要原因。

  • 特点
    开箱即用
    var rwm = sync.RWMutex
  • 写锁定和写解锁
    rwm.Lock()
    rwm.Unlock()
  • 读锁定和读解锁
    rwm.RLock()
    rwm.RUnlock()
  • 读写锁的读锁和写锁不能交叉相互解锁,否则会发生panic
func rwMutex() {
 var rwm sync.RWMutex
 rwm.Lock()
 fmt.Println("locked")
 rwm.RUnlock()
}
  • 对于读写锁,同一资源可以同时有多个读锁定

在goroutine中,写解锁会试图唤醒所有想要进行读锁定而被阻塞的goroutine。

而读解锁会在已无任何读锁定的情况下,试图唤醒一个想进行写锁定而被阻塞的goroutine。

func rwMutex() {
 var rwm sync.RWMutex

 for i := 0; i <= 2; i++ {
 go func(i int) {
 fmt.Printf("go(%d) start lock\n", i)
 rwm.RLock()
 fmt.Printf("go(%d) locked\n", i)
 time.Sleep(time.Second * 2)
 rwm.RUnlock()
 fmt.Printf("go(%d) unlock\n", i)
 }(i)
 }
 // 先sleep一小会,保证for的goroutine都会执行
 time.Sleep(time.Microsecond * 100)
 fmt.Println("main start lock")
 // 当子进程都执行时,且子进程所有的资源都已经Unlock了
 // 父进程才会执行
 rwm.Lock()
 fmt.Println("main locked")
 time.Sleep(time.Second)
 rwm.Unlock()
}

参考

互斥锁、条件锁、读写锁以及自旋锁:https://www.zhihu.com/question/66733477
https://www.cnblogs.com/cangqinglang/p/13328217.html
https://laravelacademy.org/post/19901.html


本文来自:简书

感谢作者:林桉

查看原文:go-锁机制

相关阅读 >>

Golang中使用rand产生随机不重复数字

Go - 统一定义 api 错误码

Go 语言和 java 比较?

Go - 如何解析 json 数据?

前 言

python、Golang、java、c++哪个薪资高?小白必看!

Golang一行代码把array/slice转成逗号分隔的字符串

awesome Go!高玩Gopher都会参考的Go资源集合

Golang 协程(Goroutine) 运行过程 与 并发

Go - struct{} 实现 interface{}

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...