Golang中的协程(goroutine)

简介: Golang中的协程(goroutine)

进程


 进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间。一个进程至少有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("主程序退出。。。")
}


相关文章
|
9月前
|
存储 监控 Linux
Golang 语言的 goroutine 调度器模型 GPM
Golang 语言的 goroutine 调度器模型 GPM
47 0
|
16天前
|
Go
GoLang 使用 goroutine 停止的几种办法
GoLang 使用 goroutine 停止的几种办法
16 2
|
6天前
|
安全 Go 调度
协程(goroutine)和通道(channel)是其并发模型
协程(goroutine)和通道(channel)是其并发模型
5 0
|
2月前
|
监控 Go 开发者
Golang深入浅出之-Goroutine泄漏检测与避免:pprof与debug包
【5月更文挑战第2天】本文介绍了Go语言并发编程中可能遇到的Goroutine泄漏问题,以及如何使用`pprof`和`debug`包来检测和防止这种泄漏。常见的问题包括忘记关闭channel和无限制创建goroutine。检测方法包括启动pprof服务器以监控Goroutine数量,使用`debug.Stack()`检查堆栈,以及确保每个Goroutine有明确的结束条件。通过这些手段,开发者可以有效管理Goroutine,维持程序性能。
82 7
|
2月前
|
监控 负载均衡 算法
Golang深入浅出之-Go语言中的协程池设计与实现
【5月更文挑战第3天】本文探讨了Go语言中的协程池设计,用于管理goroutine并优化并发性能。协程池通过限制同时运行的goroutine数量防止资源耗尽,包括任务队列和工作协程两部分。基本实现思路涉及使用channel作为任务队列,固定数量的工作协程处理任务。文章还列举了一个简单的协程池实现示例,并讨论了常见问题如任务队列溢出、协程泄露和任务调度不均,提出了解决方案。通过合理设置缓冲区大小、确保资源释放、优化任务调度以及监控与调试,可以避免这些问题,提升系统性能和稳定性。
65 6
|
2月前
|
Java Go
Golang深入浅出之-Goroutine泄漏检测与避免:pprof与debug包
【5月更文挑战第1天】本文介绍了Go语言中goroutine泄漏的问题及其影响,列举了忘记关闭通道、无限循环和依赖外部条件等常见泄漏原因。通过引入`net/http/pprof`和`runtime/debug`包,可以检测和避免goroutine泄漏。使用pprof的HTTP服务器查看goroutine堆栈,利用`debug`包的`SetGCPercent`和`FreeOSMemory`函数管理内存。实践中,应使用`sync.WaitGroup`、避免无限循环和及时关闭通道来防止泄漏。理解这些工具和策略对维护Go程序的稳定性至关重要。
59 4
|
2月前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
34 1
|
2月前
|
程序员 Go 数据处理
|
2月前
|
程序员 Go 调度
第十六章 Golang中goroutine和channel
第十六章 Golang中goroutine和channel
34 3
|
9月前
|
Go
Golang 语言怎么控制并发 goroutine?
Golang 语言怎么控制并发 goroutine?
20 0