协程:轻量级线程
在 Go 语言中,协程(goroutine)是轻量级的线程。它们允许开发者创建大量的并发任务,而不会像传统线程那样消耗过多的系统资源。
启动一个协程
使用 go
关键字来启动一个新的协程。下面是一个简单的例子:
-- -------------------- ---- ------- ------- ---- ------ - ------ ------- - ---- ----- ------- - ---- - -- -- - - -- --- - ---------------- - ----------------- ---------------- -- - ---- ------ - --- ------------ ------------- -
在这个例子中,say("hello")
是在主协程中执行的,而 go say("world")
是在新的协程中执行的。注意,由于没有同步机制,主协程可能在 say("world")
完成之前就结束了。
使用通道进行通信和同步
通道(channel)是 Go 语言中用于协程间通信和同步的重要机制。通过通道,协程可以安全地交换数据,而无需担心竞态条件。
创建通道
使用 make
函数创建通道,指定通道的数据类型:
ch := make(chan int)
发送和接收数据
发送数据到通道使用 <-
操作符:
ch <- x // 将x发送到通道ch
从通道接收数据也使用 <-
操作符:
x := <-ch // 接收ch中的值并赋给x
无缓冲通道
无缓冲通道在接收方准备好接收之前,发送操作会阻塞:
ch := make(chan int) go func() { ch <- 42 // 阻塞直到有协程接收 }() fmt.Println(<-ch) // 阻塞直到有协程发送
带缓冲通道
带缓冲通道允许在没有接收者的情况下发送一定数量的值:
ch := make(chan int, 2) // 创建一个缓冲区大小为2的通道 ch <- 42 // 不会阻塞,因为缓冲区还有空间 ch <- 43 // 不会阻塞,因为缓冲区还有空间 fmt.Println(<-ch) // 阻塞,直到有协程发送数据
选择结构:多路复用
select
语句允许协程等待多个通信操作。它类似于 switch
语句,但用于处理通道操作。
-- -------------------- ---- ------- --- -- --------- ------- --- -- --------- ------- -- ------ - --- -- ----- --- -- ------ - --- -- ----- --- --- - -- -- - - -- --- - ------ - ---- ---- -- ------ ----------------------- ----- ---- ---- -- ------ ----------------------- ----- - -
互斥锁:防止竞态条件
尽管 Go 的通道提供了强大的并发控制,但在某些情况下,你可能需要使用互斥锁(mutex)来保护共享资源。
使用互斥锁
-- -------------------- ---- ------- ------- ---- ------ - ------ ------- ------- - --- ------- --- --- ----- ---------- ---- ------------ ---------------- - ------------- ------ -------------- ---------- --------------------- ---------- - ---- ------ - ---- -- -------------- ---- - -- -- - - ----- --- - ----------- ---- -------------- -- ---------- ------------------- ------- -------- -------- -
在这个例子中,我们使用 sync.Mutex
来保护对 counter
变量的访问,确保在同一时间只有一个协程可以修改这个变量。
通过上述示例,你可以看到 Go 语言提供的强大并发工具,使得并发编程变得简单且高效。希望这些内容能够帮助你在 Go 语言的并发编程中更进一步!