Golang中互斥锁和读写互斥锁

阳光穿透心脏的1/2处 2024-03-22 16:15 175阅读 0赞

1508e5f320a04f0d93b1b35845c19ed2.gif

目录

互斥锁

使用互斥锁的示例代码

读写互斥锁

读写互斥锁的示例代码


互斥锁

在Golang中,互斥锁(Mutex)是一种基本的同步原语,用于实现对共享资源的互斥访问。互斥锁通过在代码中标记临界区来控制对共享资源的访问,从而保证同一时间只有一个 goroutine 可以访问共享资源,避免了并发访问时的数据竞争和不一致性问题。

互斥锁的主要方法包括两个,分别是 Lock 和 Unlock。Lock 方法用于锁定共享资源,防止其他 goroutine 访问;Unlock 方法则用于解锁共享资源,允许其他 goroutine 访问。一般来说,在使用互斥锁时,需要先通过 Lock 方法锁定共享资源,访问共享资源,然后再通过 Unlock 方法解锁共享资源,让其他 goroutine 可以访问。

使用互斥锁的示例代码

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. var count int
  7. var mutex sync.Mutex
  8. func increment() {
  9. mutex.Lock()
  10. count++
  11. mutex.Unlock()
  12. wg.Done()
  13. }
  14. func main() {
  15. for i := 0; i < 1000; i++ {
  16. wg.Add(1)
  17. go increment()
  18. }
  19. wg.Wait()
  20. fmt.Println("Final count:", count)
  21. }

在上面的示例代码中,increment函数是一个goroutine,它用来对count变量进行加1操作。在函数执行前通过mutex.Lock()获取互斥锁,在函数执行结束后通过mutex.Unlock()释放互斥锁。这样就保证了同一时刻只有一个goroutine可以访问count变量,从而避免了数据竞争的问题。

需要注意的是,在使用互斥锁时,一定要注意加锁和解锁的位置,否则可能会出现死锁的问题。

读写互斥锁

Go语言中的读写互斥锁(RWMutex)是一种特殊类型的互斥锁,它允许多个协程同时读取某个共享资源,但在写入时必须互斥,只能有一个协程进行写操作。相比互斥锁,读写互斥锁在高并发读的场景下可以提高并发性能,但在高并发写的场景下仍然存在性能瓶颈。

读写互斥锁有两个方法:RLock()和RUnlock()。在读取共享资源时,可以调用RLock()方法加读锁,在读取完成后,需要调用RUnlock()方法释放读锁。在写入共享资源时,需要调用Lock()方法加写锁,在写入完成后,需要调用Unlock()方法释放写锁。当有写锁或读写锁时,不能再加读锁或写锁,直到已经释放了所有锁。

读写互斥锁的示例代码

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. var (
  8. value int
  9. rwLock sync.RWMutex
  10. waitTime time.Duration = 100 * time.Millisecond
  11. )
  12. func readValue() {
  13. rwLock.RLock()
  14. defer rwLock.RUnlock()
  15. time.Sleep(waitTime)
  16. fmt.Println("Read value:", value)
  17. }
  18. func writeValue(val int) {
  19. rwLock.Lock()
  20. defer rwLock.Unlock()
  21. time.Sleep(waitTime)
  22. value = val
  23. fmt.Println("Write value:", value)
  24. }
  25. func main() {
  26. // 读操作可以并行执行
  27. for i := 0; i < 5; i++ {
  28. go readValue()
  29. }
  30. // 写操作必须等待读操作全部结束后才能执行
  31. for i := 0; i < 5; i++ {
  32. go writeValue(i)
  33. }
  34. // 等待所有goroutine执行完毕
  35. time.Sleep(time.Second)
  36. }

在这个示例中,使用了一个全局变量value来存储值,使用了一个sync.RWMutex类型的变量rwLock来保护这个变量的读写。在readValue函数中,首先调用RLock方法获取读锁,然后等待一段时间,最后输出变量value的值。在writeValue函数中,首先调用Lock方法获取写锁,然后等待一段时间,将传入的值赋给变量value,最后输出变量value的值。

main函数中,首先启动5个goroutine来执行readValue函数,这些goroutine可以并行执行。然后启动5个goroutine来执行writeValue函数,这些goroutine必须等待所有的读操作完成后才能执行,因为它们需要获取写锁。

需要注意的是,在使用读写互斥锁时,必须保证写操作只有一个,否则就会出现竞争状态,导致数据不一致的问题。同时也需要注意使用锁的力度,避免锁的范围过大,导致性能下降。

发表评论

表情:
评论列表 (有 0 条评论,175人围观)

还没有评论,来说两句吧...

相关阅读

    相关 互斥

    一、线程互斥方式。 --- 互斥锁 1、什么是互斥锁?特点怎么样? 互斥锁是专门用于处理线程之间互斥的一种方式,它有两种:上锁状态/解锁状态。 如果互斥锁处于上锁状

    相关 互斥

    Linux中提供一把互斥锁mutex(也称之为互斥量)。 每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁。 但通过“锁”就将资源的访问变成互斥操作,而后