Go语言通过goroutine和channel提供了高并发的解决方案。
- 使用goroutine
Goroutine 是 Go 语言中并发的核心。goroutine 是轻量级的线程,它们在一个线程上下文中启动,并由 Go 的运行时管理。创建一个 goroutine 的开销极低。
package main
import (
"fmt"
"time"
)
func hello() {
fmt.Println("Hello world goroutine")
}
func main() {
go hello() // 创建一个goroutine
fmt.Println("main function")
time.Sleep(1 * time.Second) // 等待goroutine执行完成
}
- 使用channel
Channel 是 Go 语言中的一个类型,你可以通过它来发送或者接收值,这些值可以在不同的 goroutine 之间同步传递。
package main
import (
"fmt"
"time"
)
func printNumbers(numbers chan int) {
for number := range numbers {
fmt.Println(number)
}
}
func main() {
numbers := make(chan int, 5)
go printNumbers(numbers)
for i := 0; i < 5; i++ {
numbers <- i
time.Sleep(time.Second) // 模拟一些处理时间
}
close(numbers) // 关闭channel,通知printNumbers函数结束循环
}
- 使用mutex和atomic
在并发编程中,我们还需要处理共享数据的竞争问题。Go 语言提供了 sync 包中的 mutex 和 rwmutex 类型,以及 sync/atomic 包中的原子函数来处理这些问题。
package main
import (
"fmt"
"sync"
"sync/atomic"
)
var counter int32
var wg sync.WaitGroup
func increment() {
defer wg.Done()
for i := 0; i < 2; i++ {
atomic.AddInt32(&counter, 1)
}
}
func main() {
wg.Add(2)
go increment()
go increment()
wg.Wait()
fmt.Println("Counter:", counter)
}
- 使用超时和取消
在 Go 语言中,通过 context 包可以实现对 goroutine 的超时管理和取消管理。
package main
import (
"context"
"fmt"
"time"
)
func longRunningOperation(ctx context.Context) {
select {
case <-ctx.Done():
fmt.Println("Operation canceled")
return
case <-time.After(5 * time.Second):
fmt.Println("Operation completed")
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
longRunningOperation(ctx)
}
- 使用池
使用 sync.Pool 可以提高大量 goroutine 之间共享数据的效率。
package main
import (
"fmt"
"sync"
)
var pool = sync.Pool{
New: func() interface{} {
return "Initial value"
},
}
func getValue() interface{} {
return pool.Get()
}
func setValue(value interface{}) {
pool.Put(value)
}
func main() {
setValue("New value")
fmt.Println(getValue())
}
- 使用select处理多个channel