在Golang中,我们可以使用goroutines和channels来实现并发控制。goroutines是轻量级的线程,可以在程序中同时运行多个任务。channels则用于在goroutines之间传递数据和同步操作。
以下是一些常用的并发控制方法:
sync.WaitGroup
等待一组goroutines完成:package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
fmt.Printf("Goroutine %d\n", i)
}(i)
}
wg.Wait()
fmt.Println("All goroutines finished")
}
sync.Mutex
实现互斥锁,防止多个goroutines同时访问共享资源:package main
import (
"fmt"
"sync"
)
var counter int
var mutex sync.Mutex
func increment() {
mutex.Lock()
defer mutex.Unlock()
counter++
}
func main() {
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
increment()
}()
}
wg.Wait()
fmt.Println("Counter:", counter)
}
sync.RWMutex
实现读写锁,允许多个goroutines同时读取共享资源,但在写入时需要独占锁:package main
import (
"fmt"
"sync"
"time"
)
var data map[string]string
var rwMutex sync.RWMutex
func readData(key string) {
rwMutex.RLock()
defer rwMutex.RUnlock()
value := data[key]
fmt.Printf("Read %s: %s\n", key, value)
}
func writeData(key, value string) {
rwMutex.Lock()
defer rwMutex.Unlock()
data[key] = value
fmt.Printf("Write %s: %s\n", key, value)
}
func main() {
data = make(map[string]string)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
writeData("key1", "value1")
}()
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
key := fmt.Sprintf("key%d", i)
readData(key)
}(i)
}
wg.Wait()
}
sync.Cond
实现条件变量,用于在特定条件下阻塞和唤醒goroutines:package main
import (
"fmt"
"sync"
"time"
)
var cond = sync.NewCond(&sync.Mutex{})
var ready bool
func worker(id int) {
cond.L.Lock()
for !ready {
cond.Wait()
}
fmt.Printf("Worker %d started\n", id)
cond.L.Unlock()
}
func main() {
for i := 0; i < 5; i++ {
go worker(i)
}
time.Sleep(1 * time.Second)
cond.L.Lock()
ready = true
cond.Broadcast()
cond.L.Unlock()
time.Sleep(1 * time.Second)
}
这些方法可以帮助你在Golang中实现并发控制。根据你的需求选择合适的方法,并确保正确地使用锁和其他同步原语以避免竞态条件和死锁。