go 语言的并发模型

2018-10-21 杜世伟 go

Go语言的并发模型基于CSP(Communicating Sequential Processes)通信顺序进程模型,通过goroutine和channel来实现并发。Go语言的设计者希望并发成为一种简洁、高效、易于使用的机制,因此它的并发模型具备轻量、简单、安全等特点。

以下是Go语言并发模型的几个核心概念:

1. Goroutine
Goroutine是Go语言的并发执行单元,类似于线程,但它比线程更轻量。Go的运行时调度器会负责管理成千上万的goroutine,而不会给系统带来沉重的负担。

特点:

轻量:Goroutine的启动成本非常低,初始栈大小只有几KB,而不是线程的几MB。并且,栈会根据需要动态增长。


高效调度:Go的调度器会自动把goroutine分布在不同的操作系统线程上执行,程序员无需手动管理。


简单启动:通过使用关键字go,可以轻松启动一个新的goroutine。例如:

go someFunction()

2. Channel
Channel是Go语言中用来在goroutine之间传递数据的通信机制。它是类型安全的,可以通过它将一个goroutine中的数据传递到另一个goroutine。

特点:

类型安全:每个channel只能传递一种类型的数据,这种类型在定义channel时指定。


阻塞通信:默认情况下,发送和接收操作都是阻塞的。也就是说,发送操作会等待接收方准备好,接收操作会等待发送方准备好。这确保了数据传递的同步性,避免了传统并发编程中的竞态条件问题。


无缓冲和有缓冲:Channel可以是无缓冲的(阻塞模式),也可以是有缓冲的(异步模式)。无缓冲channel要求发送和接收必须同时准备好,有缓冲channel则允许发送方在接收方未准备好时先发送数据。
创建无缓冲channel:
ch := make(chan int)

创建有缓冲channel:

ch := make(chan int, 10) // 容量为10


3. Select
select语句用于在多个channel操作中进行选择,类似于多路复用器。当多个channel都有数据准备好时,select会随机选择一个进行操作。

特点:

可以等待多个channel的操作。
在有多个channel可用时,它会随机选择一个进行操作,这有助于避免偏向某个特定的channel。
示例:

select {
case msg1 := <-ch1:
    fmt.Println("received", msg1)
case msg2 := <-ch2:
    fmt.Println("received", msg2)
default:
    fmt.Println("no message received")

}


4. Mutex 和 WaitGroup
除了channel,Go语言还提供了传统的同步机制,比如互斥锁(Mutex)和等待组(WaitGroup),用于细粒度的并发控制。

Mutex:用来实现共享资源的加锁与解锁,防止多个goroutine同时访问共享资源时发生竞态条件。

var mu sync.Mutex
mu.Lock()
// 访问共享资源
mu.Unlock()
WaitGroup:用于等待一组goroutine的完成。它提供了一个简便的方式来等待多个goroutine完成工作。

var wg sync.WaitGroup
wg.Add(2)

go func() {
    defer wg.Done()
    // do something
}()

go func() {
    defer wg.Done()
    // do something
}()

wg.Wait() // 等待所有的goroutine完成


Go 并发模型的优势

简化并发编程:Go通过goroutine和channel简化了并发编程的复杂性。相比传统的线程编程,Go让并发更容易理解和实现,避免了显式的线程管理和复杂的锁机制。


轻量高效:goroutine的启动和切换成本远低于操作系统线程,使得Go程序能够轻松并发大量任务。


安全的通信机制:通过channel在goroutine之间传递数据,有效避免了共享内存带来的竞态条件问题。Go的设计哲学是“不要通过共享内存来通信,而是通过通信来共享内存”。


CSP模型解释
CSP模型提倡进程通过通信来共享数据,而不是通过共享内存。Go语言遵循这一思想,鼓励开发者用goroutine来处理任务,用channel来进行通信。这种设计避免了多个goroutine直接访问共享变量,从而减少了竞态条件的可能性。

总的来说,Go语言的并发模型通过轻量的goroutine和安全的channel通信,结合传统的同步机制,提供了一种简单、高效、安全的并发编程方式。

标签: go Goroutine Channel

Powered by emlog 沪ICP备2023034538号-1