返回

基于Go语言基础之并发基本同步原语展开探讨(二)

后端

大家好,感谢大家持续关注。今天,将梳理出的 Go语言并发知识内容,分享给大家。 请多多指教,谢谢。 本文主要介绍 sync 标准库中基本同步原语 sync.Cond、sync.Once、sync.Pool 介绍及使用。

## 一、sync.Cond

sync.Cond 是一个条件变量,用于协调多个 goroutine 之间的通信。它可以实现等待、通知和广播等操作。

```go
package main

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

func main() {
    var cond sync.Cond
    var mutex sync.Mutex

    // 初始化一个 channel 用于存储需要处理的任务
    taskQueue := make(chan int, 10)

    // 启动一个 goroutine 来处理任务
    go func() {
        for {
            // 尝试从 channel 中获取一个任务
            select {
            case task := <-taskQueue:
                // 获取到任务后处理任务
                fmt.Printf("Processing task %d\n", task)
            default:
                // 如果 channel 为空,则阻塞等待任务
                cond.L.Lock()
                cond.Wait()
                cond.L.Unlock()
            }
        }
    }()

    // 主 goroutine 向 channel 中添加任务
    for i := 0; i < 10; i++ {
        mutex.Lock()
        taskQueue <- i
        mutex.Unlock()
        // 唤醒等待任务处理的 goroutine
        cond.Signal()
    }

    // 等待所有任务处理完成
    cond.L.Lock()
    for len(taskQueue) > 0 {
        cond.Wait()
    }
    cond.L.Unlock()

    fmt.Println("All tasks processed")
}
```

## 二、sync.Once

sync.Once 用于确保某个操作只执行一次。即使多个 goroutine 同时调用 sync.Once.Do() 方法,也只会执行一次操作。

```go
package main

import (
    "fmt"
    "sync"
)

var once sync.Once

func setup() {
    fmt.Println("Setting up")
}

func main() {
    // 多个 goroutine 同时调用 once.Do() 方法
    for i := 0; i < 10; i++ {
        go once.Do(setup)
    }

    // 主 goroutine 等待所有 goroutine 执行完成
    time.Sleep(1 * time.Second)

    fmt.Println("Setup completed")
}
```

## 三、sync.Pool

sync.Pool 用于管理对象池,可以提高对象的复用效率,减少创建和销毁对象的开销。

```go
package main

import (
    "fmt"
    "sync"
)

var pool sync.Pool

type MyStruct struct {
    Value int
}

func main() {
    // 初始化对象池
    pool.New = func() interface{} {
        return &MyStruct{}
    }

    // 从对象池中获取一个对象
    obj := pool.Get().(*MyStruct)
    obj.Value = 10

    // 将对象归还给对象池
    pool.Put(obj)

    // 从对象池中再次获取一个对象
    obj2 := pool.Get().(*MyStruct)

    // 检查对象是否相同
    if obj == obj2 {
        fmt.Println("Same object")
    } else {
        fmt.Println("Different object")
    }
}
```

## 总结

sync.Cond、sync.Once 和 sync.Pool 都是 Go 语言中非常有用的基本同步原语。它们可以帮助我们解决多种并发编程问题,提高程序的性能和可靠性。

## 致谢

感谢您的阅读。如果您有任何问题或建议,请随时留言。