首页 > 其他分享 >day13 Goroutine 协程

day13 Goroutine 协程

时间:2024-07-02 09:00:00浏览次数:1  
标签:协程 fmt Goroutine Println time func day13 go main

了解计算机原理

  • 进程:计算机资源分配单位
  • 线程:cpu处理单位
  • 协程:以 特殊机制或者函数实现高并发,又称 轻量级线程

了解Goroutine

  • Go Goroutine, go语言中的协程,实现并发。
  • 关键字 go
  • 初始大小 4k,随着程序执行自动增长和删除
  • 实现多线程 并发 执行
package main

import "fmt"

func helloGoroutine() {
	for i := 0; i < 100; i++ {
		fmt.Println("hello world", i)
	}
}

func main() {
	/*
		Go Goroutine, go语言中的协程,实现并发。
		- 关键字 go
		- 初始大小 4k,随着程序执行自动增长和删除
		- 实现多线程 并发 执行
	*/

	// 使用 go 实现协程
	go helloGoroutine()
	for i := 0; i < 100; i++ {
		fmt.Println("main ", i)
	}
}

runtime包

  • 获取系统的信息的工具包
package main

import (
	"fmt"
	"runtime"
	"time"
)

func goSchedFunc() {
	go func() {
		for i := 0; i < 6; i++ {
			fmt.Println("goroutine", i)
		}
	}()
	runtime.Gosched()
	for i := 0; i < 6; i++ {
		fmt.Println("Main goroutine", i)
	}
}

func runtimeGoExitFunc() {
	// 开启一个 goroutine 线程(协程,轻量级线程)
	go func() {
		fmt.Println("Start runtimeGoExitFunc")
		test()
		fmt.Println("End runtimeGoExitFunc")
	}()
	time.Sleep(time.Second * 3) // 当前函数睡三秒

}

func test() {
	defer fmt.Println("延时关闭test函数")
	runtime.Goexit() // 终止程序,即:结束当前线程(goroutine)
	fmt.Println("执行test函数")
}

func main() {
	/*
		runtime 包
		- 获取系统的信息的工具包
	*/

	// 获取 goRoot 目录
	fmt.Println("GoRoot Path", runtime.GOROOT())

	// 获取操作系统
	fmt.Println("System", runtime.GOOS) // darwin

	// 获取CPU数量
	fmt.Println("NumCPU", runtime.NumCPU()) // 12

	// runtime.Gosched() 线程的礼让。让出时间片,即:让goroutine先执行
	goSchedFunc()

	// NumGoroutine返回当前存在的运行例程的数量。
	fmt.Println("NumGoroutine", runtime.NumGoroutine())

	// runtime.Goexit() 比肩 panic 终止程序
	runtimeGoExitFunc()
	//
}

多线程问题

  • 临界资源安全问题。多线程调用共享变量
  • 案例:售票问题
package main

import (
	"fmt"
	"time"
)

func multithreadedSharedVariableMethods() {
	shareVariable := 1
	go func() {
		shareVariable = 2
		fmt.Println("GoRoutine shareVariable:", shareVariable)
	}()
	shareVariable = 3
	time.Sleep(1 * time.Second)
	fmt.Println("main shareVariable:", shareVariable)

}
func main() {
	/*
		go 中 多线程的问题
			- 临界资源安全问题。多线程调用共享变量
			- 案例:售票问题
				-
	*/

	// 案例1。多线程共享变量
	multithreadedSharedVariableMethods()

}

sync 同步锁

  • 锁机制处理多线程抢占资源的问题
    • 某个时间段内,只允许一个 goroutine访问共享数据。当goroutine访问完毕,释放锁后,其他goroutine才能访问
    • 不要以共享内存的方式去通信,而是以通信方式去共享内存
    • 不推荐使用 锁机制。 go语言中! 其他语言基本上都是以锁的方式处理
    • go 中鼓励通过 channel 来解决 共享问题
package main

import (
	"fmt"
	"sync"
	"time"
)

// SmLock 同步锁【互斥锁】
var SmLock sync.Mutex

// Swg 同步等待组。处理子协程执行完成
var Swg sync.WaitGroup

// TickerNums 定义全局 票的数量
var TickerNums = 10

func saleTicketFunc(ticketSeller string) {
	// 卖票函数
	for {
		if TickerNums > 0 {
			fmt.Println("获取票总量:", TickerNums)
			TickerNums--
			fmt.Println("售票员:", ticketSeller, "卖出1张票", "剩余票的量:", TickerNums)

		} else {
			fmt.Println("票卖完了!")
			break
		}
	}
}

func saleTicketMainFunc() {
	// 卖票主函数
	go saleTicketFunc("张三")
	go saleTicketFunc("李四")
	go saleTicketFunc("王五")
	go saleTicketFunc("赵六")
	time.Sleep(3 * time.Second)
}

func saleTicketMutexWaitGroupFunc(ticketSeller string) {
	// 卖票函数
	for {
		// 增加锁机制,锁住共享资源
		SmLock.Lock() // 上锁
		if TickerNums > 0 {
			fmt.Println("获取票总量:", TickerNums)
			TickerNums--
			fmt.Println("售票员:", ticketSeller, "卖出1张票", "剩余票的量:", TickerNums)

		} else {
			SmLock.Unlock() // 释放锁,否则进入锁死。
			fmt.Println("票卖完了!")
			break
		}
		SmLock.Unlock() // 释放锁
	}
}
func saleTicketMutexWaitGroupMainFunc() {
	// 增加售票互斥锁,增加上同步等待组。 卖票主函数
	Swg.Add(4)
	go saleTicketMutexFunc("张三")
	go saleTicketMutexFunc("李四")
	go saleTicketMutexFunc("王五")
	go saleTicketMutexFunc("赵六")
	Swg.Wait() // 等待全部协程处理完问题
}

func saleTicketMutexFunc(ticketSeller string) {
	// defer 延时关闭 同步等待组
	defer Swg.Done()
	// 卖票函数
	for {
		// 增加锁机制,锁住共享资源
		SmLock.Lock() // 上锁
		if TickerNums > 0 {
			fmt.Println("获取票总量:", TickerNums)
			TickerNums--
			fmt.Println("售票员:", ticketSeller, "卖出1张票", "剩余票的量:", TickerNums)

		} else {
			SmLock.Unlock() // 释放锁,否则进入锁死。
			fmt.Println("票卖完了!")
			break
		}
		SmLock.Unlock() // 释放锁
	}
}
func saleTicketMutexMainFunc() {
	// 增加售票互斥锁。 卖票主函数
	go saleTicketMutexFunc("张三")
	go saleTicketMutexFunc("李四")
	go saleTicketMutexFunc("王五")
	go saleTicketMutexFunc("赵六")
	time.Sleep(3 * time.Second)
}

func main() {
	/*
		sync 包。 锁机制处理多线程抢占资源的问题
			- 某个时间段内,只允许一个 goroutine访问共享数据。当goroutine访问完毕,释放锁后,其他goroutine才能访问
			- 不要以共享内存的方式去通信,而是以通信方式去共享内存
			- 不推荐使用 锁机制。 go语言中! 其他语言基本上都是以锁的方式处理
			- go 中鼓励通过 channel 来解决 共享问题
			-
	*/

	// 普通卖票。问题:共享资源抢占,sleep处理协程等待执行完成
	saleTicketMainFunc()

	// 进阶卖票。处理:解决共享资源抢占问题。 问题:sleep处理协程等待执行完成
	saleTicketMutexMainFunc()

	// 高阶卖票。处理:解决共享资源抢占问题,解决协程等待执行完成问题
	saleTicketMutexWaitGroupMainFunc()

}

sync.WaitGroup 同步等待组

package main

import (
	"fmt"
	"runtime"
	"sync"
)

// SwgTest 定义 同步等待组
var SwgTest sync.WaitGroup

func test1() {
	defer SwgTest.Done()
	for i := 0; i < 10; i++ {
		fmt.Println("T1", i)
	}
}
func test2() {
	for i := 0; i < 10; i++ {
		fmt.Println("T2", i)
	}
	SwgTest.Done()
}

func main() {
	// 同步等待组。处理 goroutine 的等待问题

	SwgTest.Add(2) // 设定 线程 数量
	go test1()
	runtime.Gosched() // 下面的线程让出资源!
	go test2()

	// 垃圾处理: time.Sleep(time.Second * 3)
	//time.Sleep(time.Second * 1)

	// 优秀的处理: 同步等待组等待执行完成
	SwgTest.Wait()

}

sync 的 锁 Lock + WaitGroup 同步等待组

package main

import (
	"fmt"
	"sync"
)

// TickerNums2 定义全局 票的数量
var TickerNums2 = 10

// SmLock2 同步锁【互斥锁】
var SmLock2 sync.Mutex

// Swg2 同步等待组。处理子协程执行完成
var Swg2 sync.WaitGroup

func saleTicketMutexFunc2(ticketSeller string) {
	// defer 延时关闭 同步等待组
	defer Swg2.Done()
	// 卖票函数
	for {
		// 增加锁机制,锁住共享资源
		SmLock2.Lock() // 上锁
		if TickerNums2 > 0 {
			fmt.Println("获取票总量:", TickerNums2)
			TickerNums2--
			fmt.Println("售票员:", ticketSeller, "卖出1张票", "剩余票的量:", TickerNums2)

		} else {
			SmLock2.Unlock() // 释放锁,否则进入锁死。
			fmt.Println("票卖完了!")
			break
		}
		SmLock2.Unlock() // 释放锁
	}
}
func saleTicketMutexWaitGroupMainFunc2() {
	// 增加售票互斥锁,增加上同步等待组。 卖票主函数
	Swg2.Add(4)
	go saleTicketMutexFunc2("张三")
	go saleTicketMutexFunc2("李四")
	go saleTicketMutexFunc2("王五")
	go saleTicketMutexFunc2("赵六")
	Swg2.Wait() // 等待全部协程处理完问题
}
func main() {

	// 高阶卖票。处理:解决共享资源抢占问题,解决协程等待执行完成问题
	saleTicketMutexWaitGroupMainFunc2()
}

标签:协程,fmt,Goroutine,Println,time,func,day13,go,main
From: https://www.cnblogs.com/dengz/p/18279209

相关文章

  • 13、爬虫-协程-asyncio和异步操作-aiohttp
    概念:当程序sleep或者input、output等待的时候、cpu是处于堵塞状态的、cpu此时是不再为我们的代码服务的、所以协程就是当遇到了前面这种情况的时候可以选择性的切换到其他任务上 同步协程:asyncio当程序在睡眠的时候注意加上:awaitasyncio.sleep(2)"""多任务协程asyncio......
  • 14、爬虫-异步协程爬取西游记小说-aiohttp-aiofiles
     注意:有关所有的IO操作都要加上:await挂起 """https://dushu.baidu.com/pc/detail?gid=4306063500#小说网站https://dushu.baidu.com/api/pc/getCatalog?data={%22book_id%22:%224306063500%22}#可以拿到每个章节的bookid、cid(每个章节的id)、这里%22相当于"号htt......
  • [Golang基础]Goroutine
    协程(CoRoutine)是一种轻量级的用户态线程。简单来说,线程(thread)的调度是由操作系统负责,线程的睡眠、等待、唤醒的时机是由操作系统控制,开发者无法决定。使用协程,开发者可以自行控制程序切换的时机,可以在一个函数执行到一半的时候中断执行,让出CPU,在需要的时候再回到中断点继续执行。......
  • m2_day13 [项目周]
    课程内容:GUI图形用户界面监听攻略GUIGUI=>G=图形U=用户I=接口​图形用户接口=用户图形界面...​java.awt.*; Button重量级组件javax.swing.*;JButton轻量级组件​常见的6个步骤:1.选择容器Container和组件Component......
  • golang 爬虫修炼02 ---协程、互斥锁、读写锁、waitgroup
    协程程序:为了完成特定任务,使用某种语言编写的一组指令的集合,是一段静态的代码进程:是程序的一次执行过程。正在运行的一个程序,进程作为资源分配的单位,在内存中会为每个进程分配不同的内存区域。进程是动态的,有产生、存在、消亡的过程线程:进程可进一步细分为线程,是一个程序......
  • Go Goroutine 究竟可以开多少?(详细介绍)
    GoGoroutine究竟可以开多少?Go语言因其高效的并发处理能力而备受欢迎,而Goroutine则是Go语言实现并发编程的核心。Goroutine比传统的线程更加轻量,允许开发者轻松地处理大量并发任务。那么,Go语言中的Goroutine究竟可以开多少呢?在回答这个问题之前,我们需要先了解两个关键问题......
  • ants:强大的高性能与低成本 Go 协程池
    ants:强大的高性能与低成本Go协程池原创 K8sCat 源自开发者 2024-06-1611:28 广东 听全文源自开发者专注于提供关于Go语言的实用教程、案例分析、最新趋势,以及云原生技术的深度解析和实践经验分享。256篇原创内容公众号在开发高并发程序时,管理并发......
  • 爬虫 | 多线程、多进程、协程
    进程和线程"""进程中至少有一条线程,线程和进程的开启非常类似,这里就展示线程"""fromthreadingimportThreadfrommultiprocessingimportProcess#第一种开启的方法就是直接defdeffunc(name):foriinrange(100):print(name,i)if__name__=='__ma......
  • Go语言goroutine调度器初始化
    1、调度器初始化调用点:src/runtime/asm_amd64.s:349 -> CALLruntime·schedinit(SB)runtime/proc.go:526funcschedinit(){//raceinitmustbethefirstcalltoracedetector.//Inparticular,itmustbedonebeforemallocinitbelowcallsracemapshadow.......
  • Python中的协程
    1.引言在现代软件开发中,处理高并发任务已成为常态。Python,作为一种广泛使用的高级编程语言,提供了强大的并发模型,其中协程是关键组件。本文将深入探讨Python中的协程,从基础概念到高级应用,以及它们在实际开发中的使用。2.协程的基本概念在深入探讨Python协程之前,我们需要......