浅析Golang中的协程(goroutine)

作者:周小末天天开心 时间:2024-04-29 13:05:08 

进程

进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间。一个进程至少有5种基本状态:初始状态,执行状态,等待状态,就绪状态,终止状态。通俗的讲,进程就是一个正在执行的程序。

线程

线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单位。一个进程可以创建多个线程,同一个进程中的多个线程可以并发执行,一个程序要运行的话至少有一个进程。

并发

并发是指在同一时间段内处理多个任务,通过多个任务之间的切换,使得在表面上看来是同时进行的。在 Go 语言中,可以使用 goroutine 和 channel 实现并发编程。

特点:

  • 多个任务作用在一个CPU上面

  • 同一时间点只能有一个任务执行

  • 同一时间段内执行多个任务

并行

并行是指同时处理多个任务,即多个任务同时在不同的处理器上进行执行。并行可以显著提高程序的性能,特别是在多核 CPU 中,能够利用多个 CPU 核心进行计算。在 Go 语言中,可以使用 goroutine 和 runtime 包的 GOMAXPROCS 函数实现并行编程。

特点:

  • 多个任务作用在多个CPU上面

  • 同一时刻执行多个任务

通俗的讲,多线程程序在单核CPU上面运行就是并发,多线程程序在多核CUP上运行就是并行,如果线程数大于CPU核数,则多线程程序在多个CPU上面运行既有并行也有并发。

协程(goroutine)

在 Go 语言中,协程(goroutine)是轻量级的线程,它是 Go 语言中实现并发编程的基础。与传统的线程相比,协程的创建和切换都非常轻量级,可以在单个线程内创建成千上万个协程,且切换开销非常小,因此可以实现高效的并发编程。

Go 语言中的协程是由 Go 运行时调度器(scheduler)进行管理和调度的。当程序启动时,Go 运行时会默认启动一个主协程,主协程会创建其他的子协程,这些协程会被分配到不同的系统线程上进行执行。当某个协程发生阻塞时,Go 运行时会将该协程挂起并让出 CPU,转而执行其他协程,以充分利用系统资源。

在 Go 语言中,创建协程非常简单,只需要在函数调用前加上 go 关键字即可。

例如:

func main() {
   go func() {
       fmt.Println("Hello, world!")
   }()
}

使用sync.WaitGroup等待协程执行完毕

func test1() {

for i := 0; i < 10; i++ {

//每100毫秒输出一次

fmt.Println("test1() 你好Golang-", i)

time.Sleep(time.Millisecond * 100)

}

wg.Done() //协程计数器加-1

}

func main() {
   //注意:

//1.主线程执行完毕后即使协程没有执行完毕程序也会退出

//2.协程可以在主线程没有执行完毕前提前退出,协程是否执行完毕不会影响主线程的执行

//为了保证我们的程序可以顺利执行,我们想让协程执行完毕后再执行主进程退出,

//这个时候我们可以使用sync.WaitGroup等待协程执行完毕

wg.Add(1)  //协程计数器加1

go test1() //表示开启一个协程

for i := 0; i < 10; i++ {

//每50毫秒输出一次

fmt.Println("mian() 你好Golang-", i)

time.Sleep(time.Millisecond * 50)

}

wg.Wait() //等待协程执行完毕

fmt.Println("主线程退出。。。")
}

多协程和多线程

Golang中每个goroutine(协程)默认占用内存比Java、C的线程少。OS线程(操作系统线程)一般都有固定的栈内存(通常为2MB左右),一个goroutine(协程)占用内存非常少,只有2KB左右,多协程切换调度开销方面远比线程要少。这也是为什么越来越多的大公司使用Golang的原因之一。

func test1() {

for i := 0; i < 10; i++ {

//每100毫秒输出一次

fmt.Println("test1() 你好Golang-", i)

time.Sleep(time.Millisecond * 100)

}

wg.Done() //协程计数器加-1

}

func test2() {

for i := 0; i < 10; i++ {

//每100毫秒输出一次

fmt.Println("test2() 你好Golang-", i)

time.Sleep(time.Millisecond * 100)

}

wg.Done() //协程计数器加-1

}

func main() {
   wg.Add(1)  //协程计数器加1

go test1() //表示开启一个协程

wg.Add(1)  //协程计数器加1

go test2() //表示开启一个协程

wg.Wait()

fmt.Println("主程序退出。。。")
}

来源:https://blog.csdn.net/weixin_71646897/article/details/130787446

标签:Golang,协程,goroutine
0
投稿

猜你喜欢

  • golang jwt+token验证的实现

    2024-05-05 09:34:04
  • SQL数据库操作类

    2009-01-14 16:26:00
  • MySQL在命名用过程中所遇到的常见问题

    2008-12-05 16:03:00
  • 浅谈django channels 路由误导

    2021-12-11 00:27:09
  • HTML5 Canvas 起步(1) - 基本概念

    2009-04-21 13:14:00
  • 跟老齐学Python之折腾一下目录

    2021-10-07 03:07:52
  • 如何用python批量发送工资条邮件

    2021-03-07 10:53:09
  • 三大原因:按照新HTML标准设计网页好处

    2008-11-12 11:23:00
  • SQL Transcation的一些总结分享

    2012-08-21 10:21:28
  • 在pytorch中如何查看模型model参数parameters

    2021-12-04 22:43:29
  • windows环境下tensorflow安装过程详解

    2021-12-10 15:59:34
  • js拖拽效果的原理及实现

    2024-04-10 10:43:29
  • 关于reduce的介绍及用法说明

    2024-04-18 10:49:34
  • 远程过程调用RPC基本概念及实现原理

    2022-09-24 06:45:30
  • python调用腾讯云实名认证接口辨别身份证真假

    2023-07-26 08:20:18
  • Python编写带选项的命令行程序方法

    2023-11-18 20:47:35
  • python实现ip地址查询经纬度定位详解

    2021-09-13 08:01:52
  • caffe的python接口绘制loss和accuracy曲线

    2021-06-15 23:54:21
  • JS前端加密算法示例

    2024-04-22 22:18:28
  • Python中反射和描述器总结

    2022-06-18 09:38:22
  • asp之家 网络编程 m.aspxhome.com