Golang中的互斥锁Mutex与读写锁RWMutex详解

开发 前端
本文讲解了互斥锁和读写锁的特点,两种锁都可以用于协调多个并发访问共享资源的同步机制。可以看出互斥锁适用于读写不确定,并且只有一个读或者写的场景;读写锁适用于读多写少的场景,可以有更高的性能。

Golang中的sync包实现了两种锁:互斥锁(Mutex)和读写锁(RWMutex)。

互斥锁(sync.Mutex)

  • 使用Lock方法加锁,使用Unlock方法解锁,Golang从1.18新增了TryLock方法,用于尝试获取锁,返回成功或者失败;
  • 如果Mutex被一个goroutine获取后,其他goroutine只能等到这个goroutine释放该Mutex后才能获取;
  • 使用Lock方法加锁后,不能再次加锁,直到使用Unlock方法释放锁后才能再次加锁;加锁之前使用Unlock方法会导致panic;
  • Mutex并不与特定的goroutine相关联,一个goroutine加锁,也可以使用另一个goroutine解锁;
  • 在同一个goroutine中的Mutex解锁之前再次进行加锁,会导致死锁。

互斥锁的一个经典案例是对切片进行并发安全的操作,代码如下:

package main

import (
	"fmt"
	"sync"
)

var mu sync.Mutex
var slice []int

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			for j := 0; j < 100; j++ {
				mu.Lock()
				slice = append(slice, j)
				mu.Unlock()
			}
			wg.Done()
		}()
	}
	wg.Wait()
	fmt.Println(len(slice))
}

首先定义了一个长度为0的slice,并发地对其进行了1000次append操作。

读写锁(RWMutex)

  • RWMutex该锁可以加多个读锁(RLock)或者一个写锁(Lock),Golang从1.18新增了TryLock和TryRLock方法,分别用于尝试获取写锁和读锁,返回成功或者失败。
  • 读锁被占用的情况下会阻止写,不会阻止读,多个goroutine可以同时获得读锁。
  • 写锁会阻止其他goroutine对写锁和读锁的获取。

看一个代码示例:

package main

import (
	"log"
	"sync"
)

var mu sync.RWMutex
var m map[string]string

func main() {
	m = make(map[string]string)

	mu.Lock()
	m["a"] = "A"
	mu.Unlock()

	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(i int) {
			mu.RLock()
			log.Println(m["a"]) // 并发读
			mu.RUnlock()
			wg.Done()
		}(i)
	}
	wg.Wait()
}

首先定义了一个map,然后对其进行了一次写操作和10次并发读操作。在并发读的时候,使用读锁来支持并发访问。

小结

本文讲解了互斥锁和读写锁的特点,两种锁都可以用于协调多个并发访问共享资源的同步机制。可以看出互斥锁适用于读写不确定,并且只有一个读或者写的场景;读写锁适用于读多写少的场景,可以有更高的性能。需要注意的是尽量避免在锁的范围内进行耗时较长的操作,以免影响性能。

责任编辑:姜华 来源: 今日头条
相关推荐

2023-03-10 15:45:03

Golang公平锁

2023-12-24 12:33:20

互斥锁Go代码

2020-08-26 08:59:58

Linux线程互斥锁

2020-09-16 07:56:28

多线程读写锁悲观锁

2024-01-29 01:08:01

悲观锁递归锁读写锁

2021-05-25 09:28:34

鸿蒙HarmonyOS应用

2009-10-12 09:02:03

SmartRWLock

2019-11-28 16:00:06

重入锁读写锁乐观锁

2021-03-22 11:27:06

C语言Peterson(皮特互斥锁

2021-03-24 08:02:58

C语言

2011-08-18 13:44:42

Oracle悲观锁乐观锁

2019-01-04 11:18:35

独享锁共享锁非公平锁

2021-07-06 08:37:29

Redisson分布式

2024-03-07 07:47:04

代码块Monitor

2022-07-14 07:01:56

Eureka读锁线程

2009-11-28 20:24:13

Linux互斥锁同步移植

2023-01-04 13:43:24

读写锁AQS共享模式

2020-04-24 15:44:50

MySQL数据库锁机制

2019-10-17 08:51:00

Java悲观锁Monitor

2022-02-14 15:07:48

进程FileChanne线程
点赞
收藏

51CTO技术栈公众号