Go goroutine协程
本文最后更新于:7 天前
1 关于进程和线程
进程(Process)
·就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个过程都有一个自己的地址空间,一个进程至少有5种基本状态,他们是: 初始态,执行态,等待状态,就绪状态,终止状态
线程
: 是进程中的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行 的基本单位
一个进程可以创建多个线程,同一个进程中的多个线程可以并发执行。一个程序要运行的话至少有一个进程
2 关于并发和并行
并发
: 多个线程竞争一个位置,竞争到的才可以执行, 每个时间段只有一个线程在执行
并行
: 多个线程可以同时执行, 每个时间段可以有多个线程同时执行
通俗的讲
: 多线程程序在单核CPU上面运行就是并发
,多程序程序在多核CPU上运行就是并行
,如果线程数大于cpu核心数,则多线程序在多个cpu上面运行既有并行又有并发
3 Golang中的协程(goroutine)以及主线程
golang中的主线程
: (可以理解为线程/也可以理解为进程),在一个Golang程序的主线程上可以起多个协程,Golang中多协程可以实现并行或者并发
协程
: 可以理解为用户级别线程,这是对内核透明的,也就是操作系统并不知道有协程的存在,是完全由用户自己的程序进行调度的。Golang的一大特色就是从语言层面原生支持协程,在函数或者方法前面go 关键字就可以创建一个协程, 可以说Golang中的协程就是goroutine
多协程特点
: Golang中每个goroutine默认占用内存远比java c的线程少,一个goroutine协程占用的内存非常小,只有2kb左右,多协程goroutine切换调度开销方面远比线程要少,这也是为什么越来越多的大公司使用Golang原因之一
4 通过代码演示
并行执行需求:
在主线程开启一个goroutine 该协程每隔50毫秒输出 “你好Golang”,在主线程中也每隔50毫秒输出”你好golang”,输出10次后,退出程序,要求主线程和goroutine 同时进行
首先我们只是开启一个协程,发现有一个bug 就是main函数不会等待协程执行完成后退出,而是自己执行完成就退出,因为main本身也是一个协程
package main
import (
"fmt"
"time"
)
func Sum() {
for i := 1; i < 10; i++ {
fmt.Println("sum() 你好golang ", i)
time.Sleep(time.Millisecond * 10)
}
}
func main() {
go Sum() //开启一个协程
for i := 1; i < 10; i++ {
fmt.Println("main() 你好py", i)
time.Sleep(time.Millisecond)
}
}
main() 你好py 1
sum() 你好golang 1
main() 你好py 2
main() 你好py 3
main() 你好py 4
main() 你好py 5
main() 你好py 6
main() 你好py 7
main() 你好py 8
main() 你好py 9
sum() 你好golang 2
使用sync.waitGroup来实现,等待所有协程执行完毕
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup //定义一个sync.waitGroup
func Sum() {
for i := 1; i < 10; i++ {
fmt.Println("sum() 你好golang ", i)
}
wg.Done() //协程计算减1
}
func sum1() {
for i := 1; i < 10; i++ {
fmt.Println("sum1() 你好shell", i)
}
wg.Done() //协程计算减1
}
func main() {
wg.Add(1) //协程计算加1
go Sum() //开启一个协程
wg.Add(1)
go sum1() //开启一个协程
wg.Wait() //等待所有协程执行完成
fmt.Println("main主线程退出")
}
sum1() 你好shell 1
sum1() 你好shell 2
sum1() 你好shell 3
sum1() 你好shell 4
sum1() 你好shell 5
sum1() 你好shell 6
sum1() 你好shell 7
sum1() 你好shell 8
sum1() 你好shell 9
sum() 你好golang 1
sum() 你好golang 2
sum() 你好golang 3
sum() 你好golang 4
sum() 你好golang 5
sum() 你好golang 6
sum() 你好golang 7
sum() 你好golang 8
sum() 你好golang 9
main主线程退出
5 设置golang 运行时占的cpu
golang程序默认占有所有核心cpu
cpuNum := runtime.NumCPU()//获取当前cpu个数
runtime.GOMAXPROCS(cpuNum - 1 ) //设置程序占有的cpu数量
6 开启多协程执行
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func test(num int) {
defer wg.Done() //最后执行wg.Done 计算器减1
for i := 1; i < 4; i++ {
fmt.Printf("协程(%v),数据%v\n", num, i)
}
}
func main() {
for i := 1; i < 5; i++ {
wg.Add(1)
go test(i)
}
wg.Wait()
fmt.Println("main退出")
}
/*
协程(4),数据1
协程(4),数据2
协程(4),数据3
协程(1),数据1
协程(1),数据2
协程(1),数据3
协程(3),数据1
协程(3),数据2
协程(3),数据3
协程(2),数据1
协程(2),数据2
协程(2),数据3
main退出
*/
7 统计素数
package main
import (
"fmt"
"time"
)
func sumS() {
for num := 2; num < 120000; num++ {
flag := true
for i := 2; i < num; i++ {
if num%i == 0 {
flag = false
break
}
}
if flag {
//fmt.Println(num)
}
}
}
func main() {
for i := 1; i < 10; i++ {
fmt.Println(i)
}
timeStart := time.Now().Unix()
sumS()
timeStop := time.Now().Unix()
fmt.Println(timeStop - timeStart)
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!