Go 协程基础:轻松入门并发编程,解析 Goroutines 的奥秘

一、协程基本使用

1、启动一个协程
  • 主线程中每个100毫秒打印一次,总共打印2次
  • 另外开启一个协程,打印10次
  • 情况一:打印是交替,证明是并行的
  • 情况二:开启的协程打印2次,就退出了(因为主线程退出了)
package main

import (
    "fmt"
    "time"
)

func test() {
    for i :=o;i<10;i++ {
        fmt.PrintIn("test() 你好golang")
        time.Sleep(time.Millisecond * 100)
    }
}

func main() {
    go test()    //表示开启一个协程
    for i:=0;i<2;i++ {
        fmt.PrintIn("main() 你好golang")
        time.Sleep(time.Millisecond * 100)
    }
}
/*
main() 你好golang
test() 你好golang
main() 你好golang
test() 你好golang
test() 你好golang
*/
 2、WaitGroup等待协程执行完毕
  • 主线程退出后所有的协程无论有没有执行完毕都会退出
  • 所以我们在主进程中可以通过WaitGroup等待协程执行完毕
    • sync.WaitGroup内部维护者一个计数器,计数器的值可以增加和减少
    • 例如当我们启动了N个并发任务时,就将计数器值增加N
    • 每个任务完成时通过调用Done()方法将计数器减1
    • 通过调用Wait来等待并发任务执行完,当计数器值为0时,表示所有并发任务已经完成

var wg sync.waitGroup      //第一步:定义一个计数器

wg.Add(1)                        //第二步:开启一个协程计数器+1

wg.Done()                        //第三步:协程执行完毕,计数器-1

wg.Wait()                        //第四步:计数器为0时退出

package main

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

var wg sync.WaitGroup         //第一步:定义一个计数器

func  test1() {
    for i :=0;i<10;i++ {
        fmt.PrintIn("test1() 你好golang",i)
        time.Sleep(time.Millisecond * 100)
    }
    wg.Done()    //协程计数器-1    //第三步:协程执行玩不,计数器-1
}

func  test2() {
    for i :=0;i<2;i++ {
        fmt.PrintIn("test2() 你好golang",i)
        time.Sleep(time.Millisecond * 100)
    }
    wg.Done()    //协程计数器-1   
}

func main() {
    wg.Add(1)    //协程计数器+1     第二不:开启一个协程计数器+1
    go test1()    //表示开启一个协程
    wg.Add(1)    //协程计数器+1
    go test2()    //表示开启一个协程

    wg.Wait()    //等待协程执行完毕... 第四步:计数器为0时退出
    fmt.PrintIn("主线程退出...")
    
}

/*
test2() 你好golang- 0
test1() 你好golang- 0
.....
test1() 你好golang- 8
test1() 你好golang- 9
主线程退出...
*/

 二、多协程案例

1、开启多个协程
  • 在Go语言中实现并发就是这样简单,我们还可以启动多个goroutine
  • 这里使用了sync.WaitGroup来实现等待goroutine执行完毕
  • 多次执行上面的代码,会发现每次打印的数字的顺序都不一致
  • 这是因为10个goroutine是并发执行的,而goroutine的调度是随机的
package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func hello(i int){
    defer wg.Done()    //goroutine结束就登记-1
    fmt.PrintIn("Hello Goroutine!",i)
}

func main() {
    for i :=0;i<10;i++ {
        wg.Add(1)    //启动一个goroutine就登记+1
        go hello(i)
    }
    wg.Wait()    //等待所有登记的goroutine都结束
}
2、多协程统计素数
  • 需求:要统计1-120000的数字中哪些是素数?goroutine for循环实现
  • 协程 统计 1-30000
  • 协程 统计 30001-60000
  •  协程 统计 60001-90000

  • 协程 统计 90001-120000

  • start:(n-1)*30000+1 end:n*30000

package main
import (
	"fmt"
	"sync"
	"time"
)
var wg sync.WaitGroup

func test(n int) {
	for num := (n-1)*30000 + 1; num < n*30000; num++ {
		if num > 1 {
			var flag = true
			for i := 2; i < num; i++ {
				if num%i == 0 {
					flag = false
					break
				}
			}
			if flag {
				fmt.Println(num, "是素数")
			}
		}
	}
	wg.Done()
}

func main() {
	start := time.Now().Unix()
	for i := 1; i <= 4; i++ {
		wg.Add(1)
		go test(i)
	}
	wg.Wait()
	fmt.Println("执行完毕")
	end := time.Now().Unix()
	fmt.Println(end - start) //1毫秒
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值