golang中sync.RWMutex和sync.Mutex

Mutex:互斥锁

type Mutex struct {
    // 包含隐藏或非导出字段
}

Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。

  1. 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex
  2. 使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.
  3. 适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁
  4. 在同一个 goroutine 中的 Mutex 解锁之前再次进行加锁,会导致死锁
func (m *Mutex) Lock()
//Lock方法锁住m,如果m已经加锁,则阻塞直到m解锁。
func (m *Mutex) Unlock()
//Unlock方法解锁m,如果m未加锁会导致运行时错误。
//锁和线程无关,可以由不同的线程加锁和解锁。

示例代码:

加锁和解锁:
package main

import (
	"fmt"
	"sync"
)

func main() {
	var L *sync.Mutex //互斥锁
	L = new(sync.Mutex)
	L.Lock()         //加锁
	defer L.Unlock() //解锁
	fmt.Println("hello")
}
//结果:hello
在解锁之前加锁会导致死锁:
package main

import (
	"fmt"
	"sync"
)

func main() {
	var L *sync.Mutex //互斥锁
	L = new(sync.Mutex)
	L.Lock() //加锁
	//defer L.Unlock() //解锁
	fmt.Println("hello")
	L.Lock()//再次加锁
}
//结果:
//hello
//fatal error: all goroutines are asleep - deadlock!

RWMutex:读写锁,RWMutex 基于 Mutex 实现

type RWMutex struct {
    // 包含隐藏或非导出字段
}

RWMutex读写互斥锁。该锁可以被同时多个读取者持有或唯一个写入者持有。RWMutex可以创建为其他结构体的字段;零值为解锁状态。RWMutex类型的锁也和线程无关,可以由不同的线程加读取锁/写入和解读取锁/写入锁。

  1. 可以加多个读锁或者一个写锁
  2. 写锁权限高于读锁,有写锁时优先进行写锁定
  3. 读锁占用的情况下会阻止写,不会阻止读,多个 goroutine 可以同时获取读锁
  4. 写锁会阻止其他 goroutine(无论读和写)进来,整个锁由该 goroutine 独占
func (rw *RWMutex) Lock()
//Lock方法将rw锁定为写入状态,禁止其他线程读取或者写入。
func (rw *RWMutex) Unlock()
//Unlock方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。

Lock() 和 Unlock():

Lock() 加写锁,Unlock() 解写锁

package main

import (
	"fmt"
	"sync"
)

func main() {
	var L *sync.RWMutex //读写锁
	L = new(sync.RWMutex)
	L.Lock() //加锁
	fmt.Println("hello")
	L.Unlock() //解锁
}

func (rw *RWMutex) RLock()
//RLock方法将rw锁定为读取状态,禁止其他线程写入,但不禁止读取。
func (rw *RWMutex) RUnlock()
//Runlock方法解除rw的读取锁状态,如果m未加读取锁会导致运行时错误。

RLock() 和 RUnlock():

1.RLock() 加读锁,RUnlock() 解读锁。
2.RLock() 加读锁时,如果存在写锁,则无法加读锁;当只有读锁或者没有锁时,可以加读锁,读锁可以加载多个。
3.在没有读锁的情况下调用 RUnlock() 会导致 panic 错误。
4.当RUnlock多于RLock时,会报错,进入死锁

发布了34 篇原创文章 · 获赞 12 · 访问量 6963

猜你喜欢

转载自blog.csdn.net/weixin_45604257/article/details/102742606
今日推荐