醋醋百科网

Good Luck To You!

Go语言零到一:同步原语(go语言通信)

引言

在 Go 语言中,sync 包提供了一系列用于同步 goroutine 的工具。这些工具可以帮助开发者避免竞态条件、管理并发任务的完成状态、保护共享资源的一致性等。

WaitGroup

  • 概述
    • WaitGroup 用于同步等待一组 goroutine 的完成。
    • 示例:
var wg sync.WaitGroup 
wg.Add(1) 
go func() { 
	defer wg.Done() 
	// 执行任务... 
}() 
wg.Wait()
  • 基本用法
    • 调用 Add 方法增加等待计数。
    • 调用 Done 方法减少等待计数。
    • 调用 Wait 方法等待所有 goroutine 完成。

Mutex(互斥锁)

  • 概述
    • Mutex 提供了互斥锁的功能,用于保护对共享资源的独占访问。
    • 示例:
var mu sync.Mutex mu.Lock() // 访问共享资源... mu.Unlock()
  • 基本用法
    • 调用 Lock 方法获取锁。
    • 调用 Unlock 方法释放锁。
    • 示例:
var mu sync.Mutex 
var count int 
go func() { 
	mu.Lock() 
	count++ 
	mu.Unlock() 
}()

Once

  • 概述
    • Once 确保某个函数只被执行一次。
    • 示例:
var once sync.Once 
once.Do(func() { 
	// 初始化代码... 
})
  • 基本用法
    • 调用 Do 方法来执行函数。
    • 示例:
var once sync.Once 
var initialized bool 
func initConfig() { 
	// 配置初始化... 
	initialized = true 
} 
go func() { 
	once.Do(initConfig) 
}()

RWMutex(读写锁)

  • 概述
    • RWMutex 提供读写锁的功能,允许多个 goroutine 同时读取共享资源,但在写入时需要独占访问。
    • 示例:
var rwmu sync.RWMutex 
rwmu.RLock() 
// 读取共享资源... 
rwmu.RUnlock()
  • 基本用法
    • 调用 RLockRUnlock 方法获取和释放读锁。
    • 调用 LockUnlock 方法获取和释放写锁。
    • 示例:
var rwmu sync.RWMutex 
var data map[string]int 
go func() { 
	rwmu.Lock() 
	data["key"] = 42 
	rwmu.Unlock() 
}()

Cond

  • 概述
    • Cond 提供条件变量的功能,用于在 goroutine 之间同步等待特定条件满足。
    • 示例:
var cond sync.Cond 
cond.L.Lock() 
cond.Wait() 
cond.L.Unlock()
  • 基本用法
    • 调用 New 方法创建一个新的条件变量。
    • 调用 Wait 方法让 goroutine 等待。
    • 调用 SignalBroadcast 方法唤醒等待的 goroutine。
    • 示例:
var cond sync.Cond 
var mu sync.Mutex 
var ready bool 
cond = sync.NewCond(&mu) 
go func() { 
	mu.Lock() 
	cond.Wait() 
 	eady = true 
	mu.Unlock() 
}() 
go func() { 
	mu.Lock() 
	cond.Signal() 
	mu.Unlock() 
}()

编码实践

// https://go.dev/play/p/D4ForBr2txT
package main

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

func main() {
	// 使用 WaitGroup 等待 goroutine 完成
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		fmt.Println("Hello from goroutine!")
	}()
	wg.Wait()

	// 使用 Mutex 保护共享资源
	var mu sync.Mutex
	var count int
	go func() {
		mu.Lock()
		count++
		mu.Unlock()
	}()
	mu.Lock()
	fmt.Println("Count:", count)
	mu.Unlock()

	// 使用 Once 确保初始化只执行一次
	var once sync.Once
	var initialized bool
	once.Do(func() {
		initialized = true
		fmt.Println("Initialized")
	})
	once.Do(func() {
		// 不会被执行
	})
	_ = initialized

	// 使用 RWMutex 允许多个 goroutine 同时读取
	var rwmu sync.RWMutex
	var data map[string]int
	data = make(map[string]int)
	data["key"] = 42
	go func() {
		rwmu.RLock()
		fmt.Println("Data:", data["key"])
		rwmu.RUnlock()
	}()
	go func() {
		rwmu.Lock()
		data["key"] = 99
		rwmu.Unlock()
	}()

	// 使用 Cond 等待特定条件
	lock := sync.Mutex{}
	var ready bool
	cond := sync.NewCond(&lock)
	go func() {
		cond.L.Lock()
		cond.Wait()
		ready = true
		cond.L.Unlock()
	}()
	go func() {
		time.Sleep(2 * time.Second)
		cond.L.Lock()
		cond.Signal()
		cond.L.Unlock()
	}()
	time.Sleep(3 * time.Second)
	fmt.Println("Ready:", ready)
}
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言