前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang的锁

golang的锁

作者头像
运维开发王义杰
发布2023-08-21 11:22:52
1540
发布2023-08-21 11:22:52
举报

在Go语言中,锁用于同步访问共享资源。Go语言提供了两种类型的锁:互斥锁(mutex)和读写锁(RWMutex)。

  1. 互斥锁(mutex):互斥锁是最基本的锁之一。它通过 Lock() 和 Unlock() 方法来控制对共享资源的并发访问。当一个 goroutine 获取到互斥锁时,其他 goroutine 将被阻塞直到该 goroutine 释放锁为止。互斥锁适合在读写比例不确定的情况下使用。
  2. 读写锁(RWMutex):读写锁是一种更高效的锁,它允许多个 goroutine 同时读取共享资源,但只允许一个 goroutine 写入共享资源。读写锁通过 RLock()、RUnlock()、Lock() 和 Unlock() 等方法来实现。读写锁适合在读操作远多于写操作的情况下使用,可以减少锁的竞争,提高并发性能。

示例代码:

// 使用互斥锁 var mu sync.Mutex

mu.Lock() // 访问共享资源 mu.Unlock()

// 使用读写锁 var rwMu sync.RWMutex

rwMu.RLock() // 读取共享资源 rwMu.RUnlock()

rwMu.Lock() // 写入共享资源 rwMu.Unlock()

以下是一个使用互斥锁的示例,其中有两个 goroutine 竞争访问一个共享变量 count:

代码语言:javascript
复制
go复制代码
package main

import (
    "fmt"
    "sync"
)

var (
    count int
    mu    sync.Mutex
    wg    sync.WaitGroup
)

func main() {
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go increment()
    }
    wg.Wait()
    fmt.Println("Final count:", count)
}

func increment() {
    mu.Lock()
    defer mu.Unlock()

    count++
    wg.Done()
}

在这个示例中,我们首先定义了一个计数器 count 和一个互斥锁 mu。然后,我们启动了 10 个 goroutine,每个 goroutine 都会调用 increment 函数来增加计数器的值。

在 increment 函数中,我们先获取互斥锁 mu,然后对计数器 count 进行加一操作,最后释放互斥锁。使用 defer 语句来确保在函数退出之前一定会释放锁。

通过互斥锁 mu 的加锁和解锁操作,我们可以保证同一时刻只能有一个 goroutine 访问共享变量 count,从而避免了竞态条件(race condition)的出现。

以下是一个使用读写锁的示例,其中有多个 goroutine 同时访问一个共享变量 data:

代码语言:javascript
复制
go复制代码
package main

import (
    "fmt"
    "sync"
)

var (
    data []int
    rwMu sync.RWMutex
    wg   sync.WaitGroup
)

func main() {
    for i := 0; i < 10; i++ {
        wg.Add(1)
        if i%2 == 0 {
            go write(i)
        } else {
            go read(i)
        }
    }
    wg.Wait()
}

func read(id int) {
    rwMu.RLock()
    defer rwMu.RUnlock()

    fmt.Printf("Goroutine %d read: %v\n", id, data)
    wg.Done()
}

func write(id int) {
    rwMu.Lock()
    defer rwMu.Unlock()

    data = append(data, id)
    fmt.Printf("Goroutine %d write: %v\n", id, data)
    wg.Done()
}

在这个示例中,我们首先定义了一个切片 data 和一个读写锁 rwMu。然后,我们启动了 10 个 goroutine,其中偶数编号的 goroutine 调用 write 函数来向 data 切片中写入数据,奇数编号的 goroutine 调用 read 函数来读取 data 切片中的数据。

在 read 函数中,我们先获取读锁 rwMu.RLock(),然后对 data 进行读取操作,最后释放读锁 rwMu.RUnlock()。由于读锁可以被多个 goroutine 同时持有,因此多个 goroutine 可以同时读取数据,不会相互阻塞。

在 write 函数中,我们先获取写锁 rwMu.Lock(),然后对 data 进行写入操作,最后释放写锁 rwMu.Unlock()。由于写锁只能被一个 goroutine 持有,因此多个 goroutine 尝试同时写入数据时会相互阻塞,直到当前持有写锁的 goroutine 释放锁为止。

通过读写锁 rwMu 的读锁和写锁操作,我们可以保证在写操作时不会有其他 goroutine 对 data 进行读或写操作,而在读操作时可以允许多个 goroutine 同时读取 data,从而提高了程序的并发性能。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维开发王义杰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档