不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • GO基础

  • 面向对象

  • 并发编程

    • 01.goroutine介绍
    • 02.协程调度GRM模型
    • 03.协程基本使用
      • 01.协程基本使用
        • 1.1 启动一个协程
        • 1.2 WaitGroup等待协程执行完毕
      • 02.多携程案例
        • 1.1 开启多个协程
        • 1.2 多协程统计素数
    • 04.Channel
    • 05.select
    • 06.并发安全和锁
    • 07.GO动态线程池
    • 08.goroutine编程
  • 常用库

  • 数据库操作

  • Beego框架

  • Beego商城

  • GIN框架

  • GIN论坛

  • 微服务

  • 设计模式

  • Go
  • 并发编程
xiaonaiqiang
2021-06-11
目录

03.协程基本使用

# 01.协程基本使用

# 1.1 启动一个协程

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

import (
	"fmt"
	"time"
)

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

func main() {
	go test() //表示开启一个协程
	for i := 0; i < 2; i++ {
		fmt.Println("main() 你好golang")
		time.Sleep(time.Millisecond * 100)
	}
}

/*
main() 你好golang
test() 你好golang
main() 你好golang
test() 你好golang
test() 你好golang
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 1.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时推出
      
      1
      2
      3
      4
package main
import (
	"fmt"
	"sync"
	"time"
)

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

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

func test2() {
	for i := 0; i < 2; i++ {
		fmt.Println("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.Println("主线程退出...")
}

/*
test2() 你好golang- 0
test1() 你好golang- 0
.....
test1() 你好golang- 8
test1() 你好golang- 9
主线程退出...
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 02.多携程案例

# 1.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.Println("Hello Goroutine!", i)
}
func main() {

	for i := 0; i < 10; i++ {
		wg.Add(1) // 启动一个goroutine就登记+1
		go hello(i)
	}
	wg.Wait() // 等待所有登记的goroutine都结束
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 1.2 多协程统计素数

  • 需求:要统计1-120000的数字中那些是素数?goroutine for循环实现

  • 1 协程 统计 1-30000

  • 2 协程 统计 30001-60000

  • 3 协程 统计 60001-90000

  • 4 协程 统计 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毫秒
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
上次更新: 2024/3/13 15:35:10
02.协程调度GRM模型
04.Channel

← 02.协程调度GRM模型 04.Channel→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式