美文网首页
2023-11-11-并发编程1

2023-11-11-并发编程1

作者: 护念 | 来源:发表于2023-11-10 16:51 被阅读0次

1. 对并发和并行的一点小认知

只有多核才有并行。

2. goroutine哲学:

通过通信去共享内存,而不是通过共享内存去通信
这也是go语言和其它语言最大的不同点。

3. main函数执行启动本质上就是启动了一个goroutine

4. 主协程和非主协程

主协程退出后,默认其它的非主协程都会退出;这就像一个boss,死掉后;它的小鬼自动消失;

5. sync.WaitGroup保证所有协助都执行完再退出。

默认情况下,主协助执行完后,如果直接退出,那么其它次协程都会消失;那么也就不能正常执行完。

为了保证所有协程(goroutine)都能正常执行,我们可以通过sync包来保证所有协程都能正常执行。

  1. 在开启一个goruntine前先添加w.Add()
  2. 在gorountine开启的函数内,defer添加 w.Done()保证释放
  3. 主协程中添加w.Wait() 等待所有协程能执行完

看代码:

package main

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

// 等效于 var w = sync.WaitGroup{} 推荐按照这个写法
var w sync.WaitGroup

func main() {
    // 迭代字母 注意这里是字符 unicode字符属于rune = int32
    for i := 'A'; i <= 'E'; i++ {
        w.Add(1) // 在开启goroutine前,每增加一个gorotinue 调用一次Add
        go PrintLetters(i)
    }

    w.Wait() // 等待所有goroutine执行完
}

func PrintLetters(ch rune) {
    defer w.Done()          // 每次运行完goroutine 标记一下
    fmt.Printf("%c\n", ch)  // 用c代替字符
    time.Sleep(time.Second) // 模拟耗费时
}

我们改成goroutine后发现程序执行总时间缩短了,因为并发执行。

上面的代码的知识点有点多;下面列出来一一说明:

6. var a xx结构体

  1. var a Person 这种写法,基本上和var a = Person{}等价
  2. 推荐var a = Person{}显示初始化
  3. var a Person之所有效,机理在于go的变量定义会给默认值,比如整数的默认值就是0

7. 字符的类型为rune = int32

  1. 因为是整数,所以可以执行加法
// 迭代字母 注意这里是字符 unicode字符属于rune = int32
    for i := 'A'; i <= 'E'; i++ {
        //xxx
    }
  1. 打印字符通过%c
fmt.Printf("%c\n", ch)

8. runtime包runtime.NumCPU()查看机器核心数

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println(runtime.NumCPU())
}

9. runtime.GOMAXPROCS()

GOMAXPROCS用于设置程序运行并行线程数,一般和物理机核心数保持一致就行;从1.5版本开始后,它的默认值就是物理机器核心;不需要手动设置,也不推荐。

10 .runtime.Gosched 让出当前gorountinue的执行

它会让出当前gorountine的执行,让其它gorountine执行, 当前gorountine也会执行;只是执行交给了go调度器。

它有点像一种谦让行为,本该自己执行,却让出,让其它代码先执行;
这是一种go提供的干预gorountine调度的方式。

10. runtime.Goexit

  1. 退出当前gorountine
  2. 退出前defere会正常执行的(放心)

相关文章

网友评论

      本文标题:2023-11-11-并发编程1

      本文链接:https://www.haomeiwen.com/subject/kvnhwdtx.html