Go 语言入门很简单:并发同步的几种方式

举报
宇宙之一粟 发表于 2022/10/31 19:42:39 2022/10/31
【摘要】 Go 语言并发同步的方式Golang Sync 包提供了同步原语,例如:​​mutex​​​​Waitgroup​​​​Pool​​​​Read​​​​Write mutex​​condition variables条件变量锁​​sync.Mutex​​ 提供了一个互斥原语,它允许共享资源的互斥,防止竞争条件。package mainimport ( "sync")func main(...

Go 语言并发同步的方式

Golang Sync 包提供了同步原语,例如:

  • ​mutex​
  • ​Waitgroup​
  • ​Pool​
  • ​Read​
  • ​Write mutex​
  • condition variables条件变量

​sync.Mutex​​ 提供了一个互斥原语,它允许共享资源的互斥,防止竞争条件。


package main

import (
    "sync"
)

func main() {

    i := 10
    mutex := &sync.Mutex{}
    mutex.Lock()
    i++
    mutex.Unlock()
}

读写锁

​sync.RWMutex​​​ 提供读写锁,它提供了与原始互斥锁类似的方法,但可以使用 ​​RLock​​​ 和 ​​RUnlock​​ 方法允许并发读取:

package main

import (
    "sync"
)

func main() {

    i := 10
    mutex := &sync.RWMutex{}
    mutex.Lock()
    // only one goroutine can access this code at a time
    i++
    mutex.Unlock()

    mutex.RUnlock()
    i++ // concurrent reads
    mutex.RUnlock()
}

上一个示例可以允许多个 goroutine 读取代码。与 ​​sync.Mutex​​ 不同,它一次只允许一个读取器和一个写入器。


Waitgroups

​sync.Waitgroup​​ 用于为 goroutine 提供阻塞机制。使用 Waitgroup,您可以阻止函数的执行,直到所有 goroutine 执行完毕。

它通过创建一个计数器来工作,该计数器保存要等待的 goroutine 的数量。一旦一个 goroutine 完成,计数器减 1。一旦计数器为 0,Waitgroup 就会解除对执行的阻塞。
要将值添加到 Waitgroup 计数器,我们可以使用 ​​​Add()​​ 方法,该方法采用整数值。

要在完成后从计数器中删除一个 goroutine,我们使用 ​​Done()​​ 方法。例如:


package main

import (
    "fmt"
    "sync"
)

func main() {
    wg := &sync.WaitGroup{}
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(x int) {
            fmt.Printf("Worker: %d running\n", x)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

在前面的示例中,我们通过使用 ​​Add()​​ 函数将 Waitgroup 计数器的值加 1。

一旦一个 goroutine 完成,我们使用 ​​Done()​​ 方法将计数器减 1。前面的代码应返回输出为:


Worker: 3 running
Worker: 1 running
Worker: 4 running
Worker: 0 running
Worker: 2 running

Once

​sync.Once​​ 原语确保一个函数只运行一次。一个例子如下所示:


package main

import (
    "fmt"
    "sync"
)

func main() {
    var once sync.Once
    RunOnce := func() {
        fmt.Println("Run once")
    }
    done := make(chan string)
    for i := 0; i < 5; i++ {
        go func() {
            once.Do(RunOnce)
            done <- "Hi"
        }()
    }
    for i := 0; i < 5; i++ {
        <-done
    }
}

运行该代码:

Run once

总结

本文涵盖了 Go sync 包提供的一些基本方法:如互斥锁、读写锁、等待组、Once 等同步原语的用法。更多原理和使用方法等待读者去探索。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。