GO语言学习之路21


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 管道
		//下次再看把
	*/
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值