Go并发

Go并发Go 程信道带缓冲的信道range 和 closeselect 语句默认选择练习:等价二叉查找树sync.Mutex练习:Web 爬虫作为语言的核心部分,Go 提供了并发的特性。这一部分概览了 goroutine 和 channel,以及如何使用它们来实现不同的并发模式。Go 程Go 程(goroutine)是由 Go 运行时管理的轻量级线程。go f(x, y, z)会启动...
摘要由CSDN通过智能技术生成


作为语言的核心部分,Go 提供了并发的特性。

这一部分概览了 goroutine 和 channel,以及如何使用它们来实现不同的并发模式。

Go 程

Go 程(goroutine)是由 Go 运行时管理的轻量级线程。

go f(x, y, z)

会启动一个新的 Go 程并执行

f(x, y, z)

f, x, y 和 z 的求值发生在当前的 Go 程中,而 f 的执行发生在新的 Go 程中。

Go 程在相同的地址空间中运行,因此在访问共享的内存时必须进行同步。sync 包提供了这种能力,不过在 Go 中并不经常用到,因为还有其它的办法(见下一页)。

package main

import (
	"fmt"
	"time"
)

func say(s string) {
   
	for i := 0; i < 5; i++ {
   
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
   
	go say("world")
	say("hello")
}

// world
// hello
// hello
// world
// world
// hello
// hello
// world
// world
// hello

信道

信道是带有类型的管道,你可以通过它用信道操作符 <- 来发送或者接收值。

ch <- v    // 将 v 发送至信道 ch。
v := <-ch  // 从 ch 接收值并赋予 v。

(“箭头”就是数据流的方向。)

和映射与切片一样,信道在使用前必须创建:

ch := make(chan int)

默认情况下,发送和接收操作在另一端准备好之前都会阻塞。这使得 Go 程可以在没有显式的锁或竞态变量的情况下进行同步。

以下示例对切片中的数进行求和,将任务分配给两个 Go 程。一旦两个 Go 程完成了它们的计算,它就能算出最终的结果。

package main

import "fmt"

func sum(s []int, c chan int) {
   
	sum := 0
	for _, v := range s {
   
		sum += v
	}
	c <- sum // 将和送入 c
}

func main() {
   
	s := []int{
   7, 2, 8, -9, 4, 0}

	c := make(chan int)
	go sum(s[:len(s)/2], c)
	go sum(s[len(s)/2:], c)
	x, y := <-c, <-c // 从 c 中接收

	fmt.Println(x, y, x+y) // -5 17 12
}

为什么上面程序输出不是 17 -5 12?
个人理解:在接收端准备好前,发送端阻塞了,即两个go程的发送操作都被阻塞了;当看到接收端准备好后,两个go程的发送操作弹栈,然后执行。
将程序修改如下:

package main

import "fmt"

func sum(s []int, c chan int) {
   
	sum := 0
	for _, v 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值