温馨提示×

Debian Golang并发编程入门教程

小樊
40
2025-10-06 13:12:16
栏目: 编程语言

Debian Golang并发编程入门教程

本教程将指导你在Debian系统上使用Golang实现并发编程,涵盖环境准备、基础并发原语(goroutines、channels)、同步工具(sync.WaitGroup、sync.Mutex)及常见并发模式(worker pool、pipeline)。


1. 准备工作:安装Golang

在Debian上安装Golang需通过包管理器完成,步骤如下:

# 更新软件包索引
sudo apt update
# 安装Golang(默认版本为最新稳定版)
sudo apt install golang-go
# 验证安装(显示版本号即成功)
go version

2. 基础概念:Goroutines与Channels

2.1 Goroutines(轻量级线程)

Goroutines是Go的核心并发单元,使用go关键字启动,无需手动管理生命周期。示例如下:

package main

import (
	"fmt"
	"time"
)

func printNumbers() {
	for i := 1; i <= 5; i++ {
		fmt.Printf("Number: %d\n", i)
		time.Sleep(1 * time.Second) // 模拟耗时操作
	}
}

func main() {
	go printNumbers() // 启动goroutine
	// 主goroutine继续执行
	for i := 1; i <= 5; i++ {
		fmt.Printf("Main: %d\n", i)
		time.Sleep(1 * time.Second)
	}
}

说明:主goroutine与printNumbers goroutine并发执行,输出交替出现。

2.2 Channels(协程间通信)

Channels用于goroutines之间的数据传递,避免共享内存的竞态条件。示例如下:

package main

import "fmt"

func worker(ch chan<- int) {
	for i := 1; i <= 5; i++ {
		ch <- i // 发送数据到channel
	}
	close(ch) // 关闭channel(通知接收方无更多数据)
}

func main() {
	ch := make(chan int) // 创建无缓冲channel
	go worker(ch)        // 启动worker goroutine
	// 从channel接收数据(阻塞直到有数据)
	for num := range ch {
		fmt.Printf("Received: %d\n", num)
	}
}

说明ch := make(chan int)创建无缓冲channel,close(ch)关闭channel,for num := range ch循环接收数据直到channel关闭。


3. 同步工具:sync包

3.1 WaitGroup(等待一组goroutines完成)

sync.WaitGroup用于等待多个goroutines执行完毕,避免主goroutine提前退出。示例如下:

package main

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

func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done() // 函数结束时通知WaitGroup
	fmt.Printf("Worker %d started\n", id)
	time.Sleep(2 * time.Second) // 模拟耗时操作
	fmt.Printf("Worker %d finished\n", id)
}

func main() {
	var wg sync.WaitGroup
	for i := 1; i <= 3; i++ {
		wg.Add(1) // 增加WaitGroup计数器
		go worker(i, &wg) // 启动goroutine(传入WaitGroup指针)
	}
	wg.Wait() // 阻塞直到计数器归零
	fmt.Println("All workers finished")
}

说明wg.Add(1)增加计数器,defer wg.Done()确保函数结束时计数器减1,wg.Wait()阻塞主goroutine直到计数器归零。

3.2 Mutex(互斥锁,解决竞态条件)

sync.Mutex用于保护共享资源,防止多个goroutines同时修改导致的数据不一致。示例如下:

package main

import (
	"fmt"
	"sync"
)

var (
	counter int
	mutex   sync.Mutex // 定义互斥锁
)

func increment() {
	mutex.Lock()         // 加锁(阻塞直到获取锁)
	counter++           // 修改共享变量
	mutex.Unlock()       // 解锁
}

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			increment()
		}()
	}
	wg.Wait()
	fmt.Printf("Final counter: %d\n", counter) // 输出: 1000
}

说明mutex.Lock()mutex.Unlock()包裹共享变量的修改操作,确保同一时刻只有一个goroutine能访问。


4. 常见并发模式

4.1 Worker Pool(限制并发数量)

Worker Pool模式通过固定数量的goroutines处理任务,避免资源耗尽。示例如下:

package main

import (
	"fmt"
	"sync"
)

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
	defer wg.Done()
	for job := range jobs {
		fmt.Printf("Worker %d processing job %d\n", id, job)
		results <- job * 2 // 处理结果发送到results channel
	}
}

func main() {
	const numJobs = 5
	const numWorkers = 3
	jobs := make(chan int, numJobs)
	results := make(chan int, numJobs)
	var wg sync.WaitGroup

	// 启动worker goroutines
	for w := 1; w <= numWorkers; w++ {
		wg.Add(1)
		go worker(w, jobs, results, &wg)
	}

	// 发送任务到jobs channel
	for j := 1; j <= numJobs; j++ {
		jobs <- j
	}
	close(jobs) // 关闭jobs channel(通知worker无更多任务)

	wg.Wait() // 等待所有worker完成
	close(results) // 关闭results channel

	// 打印处理结果
	for result := range results {
		fmt.Printf("Result: %d\n", result)
	}
}

说明numWorkers控制并发数量,jobs channel分发任务,results channel收集结果。

4.2 Pipeline(流水线模式)

Pipeline模式将多个处理步骤串联,每个步骤由独立的goroutine完成,前一步的输出作为下一步的输入。示例如下:

package main

import "fmt"

// generate生成0~9的整数
func generate() <-chan int {
	ch := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			ch <- i
		}
		close(ch)
	}()
	return ch
}

// square计算输入整数的平方
func square(in <-chan int) <-chan int {
	out := make(chan int)
	go func() {
		for i := range in {
			out <- i * i
		}
		close(out)
	}()
	return out
}

func main() {
	// 构建pipeline:generate -> square
	for num := range square(generate()) {
		fmt.Println(num) // 输出0,1,4,9,...,81
	}
}

说明generate函数生成数据,square函数处理数据,pipeline模式提高了代码的可读性和可维护性。


5. 注意事项

  • 避免竞态条件:共享资源必须用sync.Mutexsync.RWMutex保护。
  • 防止死锁:确保channel的发送与接收配对,避免goroutines相互等待。
  • 合理使用缓冲channel:无缓冲channel(make(chan T))会阻塞发送/接收操作,缓冲channel(make(chan T, size))可提高吞吐量,但需根据场景选择。

通过本教程,你已掌握Debian下Golang并发编程的基础知识。建议通过官方文档进一步学习select语句、context包等高级特性,提升并发编程能力。

0