golang中的sync包

目录


    在 Go 语言中,sync 包提供了用于处理并发控制的基本原语,它是 Go 语言标准库的一部分,主要用于解决多线程或多协程环境下的数据同步问题。以下是 sync 包中一些核心类型和组件的简要说明:

    1. sync.Mutex

      • Mutex 是 Mutual Exclusion(互斥锁)的缩写,是一个简单的互斥锁类型,用于保护在并发环境中可能会同时被多个协程修改的数据。通过调用 Lock() 获取锁来阻止其他协程访问受保护的代码段,完成操作后通过 Unlock() 释放锁。
    2. sync.RWMutex

      • RWMutex 是 Read-Write Mutex(读写互斥锁),比 Mutex 提供了更多的灵活性,它可以支持多个读取者同时访问但只允许一个写入者。有 RLock() 用于获取读锁和 RUnlock() 用于释放读锁;Lock()Unlock() 则用于获取和释放写锁。
    3. sync.Once

      • Once 类型保证某个动作在其生命周期内仅被执行一次,这对于初始化或其他只需要执行一次的操作非常有用。它有一个方法 Do(func()),该函数接收一个无参数无返回值的函数作为参数,确保这个函数在整个程序运行期间只被执行一次。
    4. sync.WaitGroup

      • WaitGroup 用于等待一组 goroutine 完成任务。通过 Add(delta int) 增加待完成的任务数量,每个已完成任务的 goroutine 调用 Done() 减少任务数,而主线程或者其他等待goroutine可以通过 Wait() 阻塞直到所有任务完成。
    5. sync.Map

      • Map 是一个并发安全的映射容器,设计用来在高并发环境下替代普通的 map。它通过内部维护两个映射(read 和 dirty)以及适当的锁机制来优化读写性能。它允许并发读取,同时保证写入操作的安全性。
    6. sync.Pool

      • Pool 提供了一种临时对象重用的机制,以减少内存分配的压力。Pool 可以存储并复用任意类型的值,当需要新值时可以从池中获取,不再需要时归还到池中,从而避免频繁地创建和销毁小对象。
    7. sync.Cond

      • Cond 实现了条件变量,允许一组 Goroutines 在满足特定条件时相互通知。通过与互斥锁配合使用,Cond 提供了 Broadcast()Signal() 用于发送信号唤醒等待的 Goroutine,以及 Wait() 方法让当前 Goroutine 在条件不满足时等待。

    总结来说,Go 语言的 sync 包为编写高性能且线程安全的并发代码提供了强大的基础工具集。在实际应用中,开发者可以根据具体需求选择合适的同步原语来控制并发流程。


    以下是一些使用 sync 包中不同组件的简单示例:

    1. 使用 sync.Mutex 的例子:
    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    var count int
    var mutex = &sync.Mutex{}
    
    func increment() {
    	mutex.Lock()
    	count++
    	fmt.Println("Count:", count)
    	mutex.Unlock()
    }
    
    func main() {
    	var wg sync.WaitGroup
    	for i := 0; i < 10; i++ {
    		wg.Add(1)
    		go func() {
    			defer wg.Done()
    			increment()
    		}()
    	}
    	wg.Wait()
    }
    

    在这个示例中,我们使用 Mutex 来保护对共享变量 count 的并发访问,防止竞态条件。

    1. 使用 sync.WaitGroup 的例子:
    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    func worker(id int, wg *sync.WaitGroup) {
    	defer wg.Done()
    	fmt.Printf("Worker %d started\n", id)
    	// 模拟耗时工作
    	for i := 0; i < 5; i++ {
    		fmt.Printf("Worker %d is working...\n", id)
    	}
    	fmt.Printf("Worker %d finished\n", id)
    }
    
    func main() {
    	var wg sync.WaitGroup
    	for i := 1; i <= 3; i++ {
    		wg.Add(1)
    		go worker(i, &wg)
    	}
    	wg.Wait()
    	fmt.Println("All workers have finished.")
    }
    

    在这个示例中,我们启动了3个worker goroutine,并使用 WaitGroup 确保所有worker完成工作后再结束main函数。

    1. 使用 sync.Once 的例子,保证初始化只执行一次:
    package main
    
    import (
    	"fmt"
    	"sync"
    )
    
    var once sync.Once
    var message string
    
    func setup() {
    	message = "Hello, World!"
    	fmt.Println("Setting up the message")
    }
    
    func printMessage() {
    	once.Do(setup)
    	fmt.Println(message)
    }
    
    func main() {
    	printMessage()
    	printMessage()
    }
    

    在这个示例中,setup 函数只会执行一次,尽管 printMessage 被调用了多次。这是因为 Once.Do 方法确保了传入的函数只执行一次。

    posted @   guanyubo  阅读(161)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · 全程不用写代码,我用AI程序员写了一个飞机大战
    · DeepSeek 开源周回顾「GitHub 热点速览」
    · 记一次.NET内存居高不下排查解决与启示
    · MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
    · .NET10 - 预览版1新功能体验(一)
    点击右上角即可分享
    微信分享提示