Hike News
Hike News

Golang多線程初識-day25-goroutine

多線程編程(併發)

  • 在C++, Java中創建線程,亦必須實現線程池管理線程;亦須解決線程之間數據共享的問題
  • goroutine 用於golang中的併發,屬於輕量級的線程
    • 不需考慮線程池如何實現(由golang中的runtime管理)
    • 創建goroutine非常方便(go)

進程與線程

進程

  • 進程是程序在操作系統中的一次執行過程,系統進行資源分配和調度的一個獨立單位
  • 進程是程序運行的一個實例

線程

  • 線程是進程的一個執行實體,是CPU調度和分派的基本單位,他是比進程更小的能獨立運行的基本單位
  • 一個程序中即使沒有創建任何線程,也有一個主線程在運行(一個進程之中至少有一個線程)
  • 一個進程之中可創建大於一個的線程

tips

  • 一個進程可以創建銷毀多個線程;同一個進程中的多個線程之間可併發執行
  • 兩個線程執行是互不相影響的
  • 一個進程中只有一個線程在執行:單線程程序
  • 一個進程中有多個線程在執行:多線程程序
  • 一個進程中創建多個子進程執行程序:多進程程序(nginx)

併發與併行

concurrency vs parallelism

併發

多線程程序在一個核的CPU上運行

  • 同一時刻只有一個線程在跑,只是間隔的時間很短
  • 當創建了子線程時,主線程要是執行結束便直接退出,不會管子線程結束了沒

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
)

func test(){
for i:=0;i<100;i++{
fmt.Println(i)
}
}

func main(){
go test()
}

result

1
2


  • 因主線程創建好子線程時就繼續往下執行
  • 因此不管子線程是否有將程序執行完畢,當主線程執行結束時程序就結束了
  • 要避免此情況,最簡單方法可在主線程使用time.Sleep()等待子線程執行完畢再退出

example 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"fmt"
"time"
)

func test(){
for i:=0;i<100;i++{
fmt.Println(i)
}
}

func main(){
go test()

//加入等待時間等待子線程結束任務
time.Sleep(time.Second)
}

result

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

並行

多線程程序在多個核的CPU上運行

  • 任一時刻有一個以上的線程在執行程序
  • 只在多核的CPU上才得以實現

協程與線程

協程

  • 擁有獨立的棧空間,且共享堆空間,調度由用戶自己控制
  • 本質上類似於用戶級線程,這些用戶級線程也是自己實現的

線程

  • 一個線程上可以跑多個協程,協程是輕量級的線程
  • 一個物理線程可以執行多個goroutine協程

設置golang運行的cpu核數

  • golang v1.8版本之前需設定運行golang時所需要的CPU核心數(未設置則跑在單核心上)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package main

    import (
    "runtime"
    )

    func main(){
    CpuNum := runtime.NumCPU()
    runtime.GOMAXPROCS(CpuNum)
    }
  • 1.8以上的版本默認將程序跑在所有的核上