多线程编程
本文档介绍Go语言中的多线程编程技术,包括Goroutine管理、同步机制、并发安全等实践方法。
📋 目录
Goroutine管理
在Go语言中,Goroutine是轻量级的并发执行单元,由Go运行时管理。以下是管理Goroutine的常用方法:
启动Goroutine
1. 使用go关键字启动函数
go
package main
import (
"fmt"
"time"
)
func someFunction(name string) {
for i := 0; i < 3; i++ {
fmt.Printf("%s: %d\n", name, i)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go someFunction("goroutine-1") // 启动新的goroutine
go someFunction("goroutine-2") // 启动另一个goroutine
someFunction("main") // 主goroutine执行
// 等待其他goroutine完成
time.Sleep(time.Second)
}2. 使用匿名函数创建Goroutine
go
func main() {
// 匿名函数goroutine
go func() {
fmt.Println("匿名函数goroutine执行")
}()
// 带参数的匿名函数goroutine
go func(msg string) {
fmt.Printf("消息: %s\n", msg)
}("Hello from goroutine")
time.Sleep(time.Second)
}3. 闭包Goroutine
go
func closureExample() {
messages := []string{"Hello", "World", "Go"}
for i, msg := range messages {
// 正确的闭包使用方式
go func(index int, message string) {
fmt.Printf("Index: %d, Message: %s\n", index, message)
}(i, msg)
// 错误的闭包使用(会产生竞态条件)
// go func() {
// fmt.Printf("Index: %d, Message: %s\n", i, msg)
// }()
}
time.Sleep(time.Second)
}Channel通信
使用Channel在Goroutine之间进行安全的数据传输和同步:
1. 基本Channel操作
go
func basicChannelExample() {
ch := make(chan int) // 创建无缓冲通道
go func() {
ch <- 42 // 发送数据到通道
fmt.Println("数据已发送")
}()
value := <-ch // 从通道接收数据
fmt.Printf("接收到的值: %d\n", value)
}2. 缓冲Channel
go
func bufferedChannelExample() {
ch := make(chan string, 3) // 创建缓冲通道,容量为3
// 发送数据(不会阻塞,因为有缓冲)
ch <- "message 1"
ch <- "message 2"
ch <- "message 3"
// 接收数据
for i := 0; i < 3; i++ {
msg := <-ch
fmt.Printf("接收到: %s\n", msg)
}
}3. 双向通信
go
func bidirectionalCommunication() {
request := make(chan string)
response := make(chan string)
// 工作goroutine
go func() {
for {
req := <-request
if req == "quit" {
break
}
response <- fmt.Sprintf("处理了: %s", req)
}
}()
// 发送请求
request <- "任务1"
fmt.Println(<-response)
request <- "任务2"
fmt.Println(<-response)
request <- "quit"
}同步机制
sync.WaitGroup
WaitGroup用于等待一组Goroutine完成:
go
import (
"fmt"
"sync"
"time"
)
func waitGroupExample() {
var wg sync.WaitGroup
// 启动3个goroutine
for i := 1; i <= 3; i++ {
wg.Add(1) // 增加等待计数
go func(id int) {
defer wg.Done() // 完成时减少计数
fmt.Printf("Goroutine %d 开始工作\n", id)
time.Sleep(time.Duration(id) * time.Second)
fmt.Printf("Goroutine %d 完成工作\n", id)
}(i)
}
wg.Wait() // 等待所有goroutine完成
fmt.Println("所有goroutine都已完成")
}
func main() {
var wg sync.WaitGroup
wg.Add(1) // 增加等待组的计数器
go func() {
defer wg.Done() // 减少等待组的计数器
// goroutine 执行的代码
}()
wg.Wait() // 等待所有 goroutine 完成
}这些是在 Go 中操作 goroutine 的一些常用方法和技术。goroutine 提供了一种轻量级的并发机制,可以让你在 Go 中更方便地编写并发程序。通过通道和同步原语,可以有效地控制和管理 goroutine 的并发操作。