《Go语言并发之道》学习笔记(一)

Go语言并发之道学习笔记(一)

写在前面的话: 近期一直在学Go语言,并发是必不可少的,看《Go语言并发之道》做个记录,方便回顾,里面很多内容也不完善,希望有所收获

1. 基本概念

  • 并发和并行的区别
    • 并发属于代码,并行属于一个运行中的程序。
    • 我的理解是并行是指同时刻运行同一段代码(这段代码实现的功能是同时生效的),并发时同时刻可以运行不同的代码(可以是不同功能的代码)
  • sync 和 channel 的区别
    • sync 对性能要求高,保护某个结构的内部状态,不关心操作的结果
    • channel 需要转让数据的所有权,协调多个逻辑判断
    • 尽量使用 channel

2. goroutine 是否改变闭包内变量的值

先来看一段代码,输出是什么?

package main
import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup
func main() {
    salutation := "hello"
    wg.Add(1)
    go func() {
        defer wg.Done()
        salutation = "welcome"
    }()
    wg.Wait()
    fmt.Println(salutation)
}
  • 输出结果:

    welcome

  • 结论:
    • goroutine在他们所创建的相同地址空间内执行

我们更改一下main部分

func main() {
    for _, salutation := range []string{"hello", "greetings", "good day"} {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println(salutation)
        }()
    }
    wg.Wait()
}
  • 输出结果:

    good day
    good day
    good day

  • 结论:

    goroutine 在运行一个闭包,在闭包使用变量 salutation 时,字符串的迭代已经结束。goroutine 开始之前循环又很高的概率会退出,意味着变量 salutation 的值不在范围内。所以 salutation 会被转移到堆中。

若要循环打出,正确方式如下:

  • 声明参数,将变量显示的映射到闭包中
  • 将当前迭代的变量传递给闭包,创建了一个字符串结构的副本,从而确保当 goroutine 运行时,我们可以引用适当的字符串
for _, salutation := range []string{"hello", "greetings", "good day"} {
    wg.Add(1)
    go func(s string) {
        defer wg.Done()
        fmt.Println(s)
    }(salutation)
}
wg.Wait()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值