当前位置: 首页 > article >正文

Go中的三种锁

Go 中的锁

Go 语言提供了多种锁机制,用于在并发编程中保护共享资源。常见的锁包括 互斥锁读写锁sync.Map 的安全锁
在这里插入图片描述


1. 互斥锁(Mutex)

原理

互斥锁(sync.Mutex)是一种最简单的锁机制,用于保护共享资源的独占访问。当一个 Goroutine 获取了互斥锁后,其他 Goroutine 必须等待锁释放才能访问共享资源。

特点
  • 独占访问:同一时间只有一个 Goroutine 可以持有锁。
  • 阻塞等待:未获取锁的 Goroutine 会阻塞,直到锁被释放。
  • 简单易用:适用于简单的临界区保护。
使用场景
  • 适用于对共享资源的独占访问场景。
  • 适用于临界区较小的场景。

2. 读写锁(RWMutex)

原理

读写锁(sync.RWMutex)是一种更高效的锁机制,允许多个 Goroutine 同时读取共享资源,但只允许一个 Goroutine 写入共享资源。

特点
  • 读共享:多个 Goroutine 可以同时获取读锁。
  • 写独占:只有一个 Goroutine 可以获取写锁,且写锁与读锁互斥。
  • 高效并发:适用于读多写少的场景。
使用场景
  • 适用于读操作远多于写操作的场景。
  • 适用于需要高并发读取共享资源的场景。

3. sync.Map 的安全锁

原理

sync.Map 是 Go 语言提供的一种并发安全的映射类型,内部通过锁机制和分段存储实现高效的并发访问。

特点
  • 并发安全:无需额外加锁即可安全地并发访问。
  • 高效读写:通过分段锁和原子操作优化性能。
  • 动态扩展:支持动态扩展存储空间。
使用场景
  • 适用于需要高并发读写的映射场景。
  • 适用于键值对数量动态变化的场景。

以下是 Go 语言中三种锁的工作原理流程图:

Go 中的锁
互斥锁 Mutex
读写锁 RWMutex
sync.Map 的安全锁
独占访问
阻塞等待
简单易用
读共享
写独占
高效并发
并发安全
高效读写
动态扩展
三种锁使用实例
互斥锁
package main

import (
    "fmt"
    "sync"
    "time"
)

var (
    counter int
    mutex   sync.Mutex
)

func increment() {
    mutex.Lock() // 加锁
    counter++
    mutex.Unlock() // 解锁
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            increment()
        }()
    }
    wg.Wait()
    fmt.Println("Final Counter Value:", counter)
}
Final Counter Value: 1000
读写锁(RWMutex)
package main

import (
    "fmt"
    "sync"
    "time"
)

var (
    data    map[string]string
    rwMutex sync.RWMutex
)

func readData(key string) string {
    rwMutex.RLock() // 加读锁
    defer rwMutex.RUnlock() // 解读锁
    return data[key]
}

func writeData(key, value string) {
    rwMutex.Lock() // 加写锁
    defer rwMutex.Unlock() // 解写锁
    data[key] = value
}

func main() {
    data = make(map[string]string)
    var wg sync.WaitGroup

    // 写操作
    wg.Add(1)
    go func() {
        defer wg.Done()
        writeData("name", "Alice")
    }()

    // 读操作
    wg.Add(1)
    go func() {
        defer wg.Done()
        fmt.Println("Name:", readData("name"))
    }()

    wg.Wait()
}
Name: Alice
sync.Map 的安全锁
package main

import (
    "fmt"
    "sync"
)

func main() {
    var sm sync.Map

    // 存储数据
    sm.Store("name", "Alice")
    sm.Store("age", 30)

    // 读取数据
    if value, ok := sm.Load("name"); ok {
        fmt.Println("Name:", value)
    }

    // 遍历数据
    sm.Range(func(key, value interface{}) bool {
        fmt.Printf("Key: %v, Value: %v\n", key, value)
        return true
    })
}
Name: Alice
Key: name, Value: Alice
Key: age, Value: 30

http://www.kler.cn/a/517104.html

相关文章:

  • IO进程 寒假作业
  • 百度APP iOS端磁盘优化实践(上)
  • Redis使用基础
  • 麒麟操作系统服务架构保姆级教程(十四)iptables防火墙四表五链和防火墙应用案例
  • Kyligence AI 数据智能体:首批亮相神州数码 DC·AI 生态创新中心!
  • 小游戏源码开发搭建技术栈和服务器配置流程
  • 实践深度学习:构建一个简单的图像分类器
  • c语言中的位域详解
  • mac 通过 Homebrew 安装 git 遇到的问题
  • ECS中实现Nginx四层和七层负载均衡以及ALB/NLB实现负载均衡
  • react install
  • Langchain+文心一言调用
  • SOME/IP服务接口
  • 干货分享|算法竞赛真题讲解2
  • Liunx上Jenkins 持续集成 Java + Maven + TestNG + Allure + Rest-Assured 接口自动化项目
  • 从语音识别到图像识别:AI如何“看”和“听”
  • 状态模式——C++实现
  • 分布式 IO 模块携手 PLC,开启设备车间降本增效新篇章
  • git cherry-pick从一个分支中选择一个或多个提交(commit)并将其应用到当前分支
  • OpenStack基础架构
  • 以Python 做服务器,N Robot 做客户端,小小UI,拿捏
  • 如何使用Midjourney生成中国蛇年的灵蛇绘画作品
  • Spring WebSocket 与 STOMP 协议结合实现私聊私信功能
  • 【Golang 面试题】每日 3 题(四十三)
  • Linux下动静态库的制作与使用
  • C#编程:List.ForEach与foreach循环的深度对比