2022/02/12
/*
//进程和线程的基本介绍
1.进程就是程序在操作系统中的一次执行过程,
是系统进行资源分配和调度的基本单位
2.线程是进程的一个执行实例,是程序执行的最小单元,
它是比进程更小的能独立运行的基本单位
3.一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行
4.一个程序至少有一个进程,一个进程至少有一个线程
//goroutine的基本介绍
1.多线程程序在单核上运行,就是并发
因为是在一个cpu上,比如有10个线程,每个线程执行10毫秒(进行轮番操作)
从人的角度看,好像这10个线程都在运行,但是从微观上看,在某个时间点,
其实只有一个线程在执行,这就是并发
2.多线程程序在多核上运行,就是并行
因为是在多个cpu上,比如10个cpu,比如有10个线程,每个线程执行10毫秒,
(各自在不同cpu上执行),从人的角度看,这10个线程都在运行,但是从微观
上看,在某一个事件点看,也同时有10个线程在执行,这就是并行
//Go协程和Go主线程
1.go主线程(有程序员直接成为线程,也可以理解为进程),在一个go线程上,
可以起多个协程,可以理解为协程是轻量级的线程
2.Go协程的特点
有独立的栈空间,共享程序堆空间,调度由用户控制,协程是轻量级的线程
*/
package main
import (
"fmt"
"strconv"
"time"
)
/*
在主线程中,开启一个goroutine,该协程没间隔一秒输出"hello,world"
在主线程中,每隔一秒输出"hello,golang",输出10次后,退出程序
要求主线程和goroutine同时执行
*/
func test() {
for i := 0; i < 10; i++ {
fmt.Println("hello,world" + strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func main() {
go test() //开启了一个协程
for i := 0; i < 10; i++ {
fmt.Println("~~~hello,golang" + strconv.Itoa(i))
time.Sleep(time.Second)
}
//如果主线程退出,协程即使还没有执行完毕,也会退出
}
package main
import (
"fmt"
"runtime"
)
/*
1.主线程是一个物理线程,直接作用在cpu上,是重量级的,非常消耗cpu资源
2.协程从主线程开启的,是轻量级的线程,是逻辑态,对资源消耗相对小
3.golang的协程机制是重要的特点,可以轻松的开启上万个协程,其他编程语言
的并发机制一般是基于线程的,开启过多的线程,资源耗费大,这里的凸显
golang在并发上的优势
4. MPG是什么
M:操作系统的主线程(是物理线程)
P:协程执行需要的上下文环境
G:协程
5.golang为了充分利用多cpu的优势,在golang程序中,可以设置运行的cpu数目
在go1.8后,默认让程序运行在多个核上,可以不用设置,设置的是runtime包
*/
func main() {
cpuNum := runtime.NumCPU()
fmt.Println("cpuNum = ", cpuNum) //cpuNum = 12
//可以设置使用多个cpu
//runtime.GOMAXPROCS(cpuNum)
}
package main
import (
"fmt"
"sync"
"time"
)
/*
要求计算1-20 的各个数的阶乘,并且把各个数的阶乘结果放入到map中
最后显示出来,要求使用goroutine完成
*/
var (
myMap = make(map[int]int, 10)
lock sync.Mutex
)
func test(n int) {
res := 1
for i := 1; i <= n; i++ {
res *= i
}
lock.Lock()
myMap[n] = res
lock.Unlock()
}
func main() {
//循环开启20个协程计算
for i := 0; i < 20; i++ {
go test(i)
}
//休眠五秒钟试下
time.Sleep(time.Second * 5)
// lock.Lock() //读的时候加锁[可能]是因为主线程不知道是否处理结束
for i, v := range myMap {
fmt.Printf("map[%d] = %d\n", i, v) //fatal error: concurrent map writes
}
// lock.Unlock()
/*
上面产生两个问题
1.数据写入时,发生资源竞争!
2.休眠多久合适呢
通过 go build -race main.go
直观的看出有2个资源竞争
*/
/*
1.解决方法一 使用全局变量加锁同步改进程序
---- 使用互斥锁 在 sync包中
//锁要声明 lock sync.Mutex
上锁 lock.Lock()
解锁 lock.Unlock()
2.解决方法二 =========channel 管道
//下次再看把
*/
}