进程是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位。
线程是进程的最小单位,是程序执行的最小单元,是进程的一个执行实例。
主线程是一个物理线程,直接作用在CPU上,是重量级的,非常耗费资源。 其他编程语言的并发机制是基于线程的,开启过多的线程,耗费资源。 go主线程(有程序员称之为线程,甚至是进程):在一个Go线程上开起多个协程,协程是轻量级的线程,是逻辑态的,对资源的耗费小。
并发和并行
1---多多---1Go语言并发通过goroutine实现,类似线程,用户轻量级的线程,但不是线程
goroutine是Go语言运行时候runtime调度实现,用户自己开的线程,属于轻量级的线程,更加地高效 。线程是操作系统层面实现的
goroutine进行通信。
channel和goroutine是实现Go语言并发模式的基础Goroutine的调度模型是MPG模式,解释为
goroutine的使用是在调用函数的前面加上关键字gogoroutine必定对应一个函数// demo
package main
import (
"fmt"
"strconv"
"time"
)
// 每隔1秒输出hello world
func test() {
for i :=1 ; i < 10; i++{
fmt.Println("test () hello world" + strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func main(){
go test() // 开启协程
for i := 1;i < 10; i++{
fmt.Println("main() hello golang" + strconv.Itoa(i))
time.Sleep(time.Second)
}
}// 开启单个goroutine
package main
import (
"fmt"
"sync"
)
// goroutine demo
var wg sync.WaitGroup
func hello(){
fmt.Println("hello xiaoming")
wg.Done() // 通知wg把计数牌减1, 直至到0结束
}
func main(){ // 开启主goroutine去执行main函数
wg.Add(1) // 计数牌+1
go hello() // 开启一个goroutine去执行hello函数;go关键字
fmt.Println("hello main") // 主goroutine做的事情
// time.Sleep(time.Second)
wg.Wait() // 主goroutine结束,小弟可能没有结束;等待上面的所有执行结束
}// 开启多个goroutine
package main
import (
"fmt"
"sync"
)
// goroutine demo
var wg sync.WaitGroup
func hello(i int){
fmt.Println("hello 小明", i)
wg.Done() // 通知wg把计数牌减1
}
func main(){ // 开启主goroutine去执行main函数
wg.Add(10000) // 计数牌+1
for i := 0; i < 10000; i++{
go hello(i) // 开启多个goroutine去执行hello函数;go关键字
}
fmt.Println("hello main") // 主goroutine做的事情
// time.Sleep(time.Second)
wg.Wait() // 等待上面的所有执行结束
}// 匿名函数
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func main(){
wg.Add(10000)
for i := 0; i<10000;i++{
// goroutine 中存在闭包的解决
go func(i int){ // 传递参数i
fmt.Println("hello", i)
wg.Done()
}(i) // i显式地传递匿名函数
}
fmt.Println("hello main")
wg.Wait() // 阻塞,等待所有的小弟干完活之后才结束
}package main
import (
"fmt"
"runtime"
)
func main() {
// 获取当前成CPU的数量
num := runtime.NumCPU()
fmt.Println(num)
// 自行设置使用多个CPU
runtime.GOMAXPROCS(num - 1)
fmt.Println("ok")
}GOMAXPROCS参数需要使用多少个OS线程来同时执行Go代码,可设置同时执行的最大CPU数,默认是机器上的CPU核心数
GO通过runtime.GOMAXPROCS()函数来设置并发执行时占用的CPU逻辑核心数GO1.5之后默认使用全部的CPU逻辑核心数// 先执行完a,再执行b
package main
import (
"fmt"
"runtime"
"sync"
)
var wg sync.WaitGroup
func a(){
for i := 1; i<10; i++{
fmt.Println("A", i)
}
wg.Done()
}
func b(){
for i := 1; i<10; i++{
fmt.Println("B", i)
}
wg.Done()
}
func main(){
runtime.GOMAXPROCS(1) // 只占用一个CPU核心
wg.Add(2) // 开启两个goroutine:a b
go a()
go b()
wg.Wait()
//time.Sleep(time.Second)
// ab同时执行,混合在一起
runtime.GOMAXPROCS(4) // 只占用4个CPU核心
wg.Add(2) // 开启两个goroutine:a b
go a()
go b()
wg.Wait()
}goroutinego程序可以同时使用多个操作系统线程goroutine和OS线程是多对多的关系,即m:n:m个goroutine分配到n个操作系统线程中,比如1000个goroutine分配到8个系统线程中