设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间11 现在时间11 缓存数据 "如果你喜欢一个人, 一定要告诉她 不是为了要她报答, 而是让她在以后黑暗的日子里, 否定自己的时候, 想起世界上还有人这么喜欢她 她并非一无是处。"

"如果你喜欢一个人, 一定要告诉她 不是为了要她报答, 而是让她在以后黑暗的日子里, 否定自己的时候, 想起世界上还有人这么喜欢她 她并非一无是处。" -- 感谢你曾来过

查看: 768|回复: 2

GO利用channel协调协程的实现

[复制链接]

  离线 

TA的专栏

  • 打卡等级:无名新人
  • 打卡总天数:1
  • 打卡月天数:0
  • 打卡总奖励:18
  • 最近打卡:2024-01-20 00:17:53
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
34
主题
24
精华
0
金钱
114
积分
66
注册时间
2023-10-4
最后登录
2025-5-26

发表于 2024-4-19 17:47:16 | 显示全部楼层 |阅读模式
目录


  • 前言
  • 使用
  • 实现生产者消费者模式
  • 实战面试题: 「交替打印数字和字母」

    • 题目
    • 解题思路

  • 结尾

前言

go 当中的并发编程是通过goroutine来实现的,利用channel(管道)可以在协程之间传递数据,实现协程的协调与同步。

使用

新建一个管道,使用make channel 来构建
  1. // 构建一个缓存长度为8 的管道
  2. ch := make(chan int ,8)
  3. // 写入
  4. ch <- 10
  5. // 取出
  6. number := <-ch
  7. // 关闭
  8. close(ch)
复制代码
注意⚠️: 取数据的时候,如果没得取,会阻塞代码的执行,如果一直没有取到,那就是死锁

实现生产者消费者模式

两个生产者者协程和一个消费者协程
使用waitGroup
  1. func main() {  
  2.     ch := make(chan int, 100)  
  3.     wg := sync.WaitGroup{}  
  4.     wg.Add(2)  
  5.     // 生产者
  6.     go func() {  
  7.         defer wg.Done()  
  8.         // 写入数据  
  9.         for i := 0; i < 10; i++ {  
  10.             ch <- i  
  11.         }  
  12.     }()  
  13.     // 生产者
  14.     go func() {  
  15.         defer wg.Done()  
  16.         // 写入数据  
  17.         for i := 0; i < 10; i++ {  
  18.             ch <- i  
  19.         }  
  20.     }()  
  21.     wg2 := sync.WaitGroup{}  
  22.     wg2.Add(1)  
  23.     // 消费者
  24.     go func() {  
  25.         sum := 0  
  26.         fmt.Printf("sum %d \n", sum)  
  27.         for {  
  28.             // 这里会等待  
  29.             temp, ok := <-ch  
  30.             // close 并且 管道为空,ok = false  
  31.             if !ok {    
  32.                 break  
  33.             } else {  
  34.                 sum += temp  
  35.             }  
  36.         }  
  37.         fmt.Printf("sum %d \n", sum)  
  38.         wg2.Done()  
  39.     }()  
  40.     // 等待俩生产者结束  
  41.     wg.Wait()  
  42.     // 生产数据之后,消费者也并行读完了,此时可以关闭 管道 来 跳出for循环了 
  43.     close(ch)  
  44.     // 等待消费者协程结束  
  45.     wg2.Wait()  
  46. }
复制代码
使用管道则将wg2相关的代码改掉
  1. func main() {  
  2.     //... 
  3.     //...
  4.     ch2 := make(chan struct{}, 0)  
  5.     go func() {  
  6.         sum := 0  
  7.         fmt.Printf("sum %d \n", sum)  
  8.         for {  
  9.             // 这里会等待  
  10.             temp, ok := <- ch  
  11.             // close 并且 管道为空,ok = false  
  12.             if !ok {  
  13.                 break  
  14.             } else {  
  15.                 sum += temp  
  16.             }  
  17.         }  
  18.         fmt.Printf("sum %d \n", sum)  
  19.         ch2 <- struct{}{}  
  20.     }()  
  21.     // 等待俩生产者结束  
  22.     wg.Wait()  
  23.     // 关闭管道
  24.     close(ch)  
  25.     // 等待消费者协程结束  
  26.     <-ch2
  27. }
复制代码
实战面试题: 「交替打印数字和字母」


题目

使用两个 goroutine 交替打印序列,一个 goroutine 打印数字, 另外一个 goroutine 打印字母, 最终效果如下:
  1. 12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728
复制代码
解题思路

利用channel的 阻塞 来协调线程,达到线程交叉执行的效果。
代码
  1. func main() {  
  2.     letter, number := make(chan bool), make(chan bool)  
  3.     wait := sync.WaitGroup{}  
  4.     go func() {  
  5.         i := 1  
  6.         for {  
  7.             if <-number {  
  8.                 fmt.Print(i)  
  9.                 i++  
  10.                 fmt.Print(i)  
  11.                 i++  
  12.                 letter <- true  
  13.             }  
  14.         }  
  15.     }()  
  16.     wait.Add(1)  
  17.     go func() {  
  18.         // 获得ASCII码  
  19.         i := 'A'  
  20.         for {  
  21.             if <-letter {  
  22.                 // 当前已经超过Z时,无需再打印
  23.                 if i > 'Z' {  
  24.                     // 停止等待,并且跳出循环
  25.                     wait.Done()  
  26.                     break  
  27.                 }  
  28.                 // 将ASCII码强转成字母输出  
  29.                 fmt.Print(string(i))  
  30.                 i++  
  31.                 fmt.Print(string(i))  
  32.                 i++  
  33.                 number <- true  
  34.             }  
  35.         }  
  36.     }()  
  37.     // 放行数字打印的阻塞
  38.     number <- true  
  39.     // 等待关闭主线程
  40.     wait.Wait()  
  41. }
复制代码
其实完全也可以将waitGroup换成管道
  1. func main() {  
  2.     letter, number := make(chan bool), make(chan bool)  
  3.     // 再定义一个管道来等待,替代waitGroup的作用
  4.     wait := make(chan bool)
  5.     // 打印数字
  6.     go func() {  
  7.         i := 1  
  8.         for {  
  9.             if <-number {  
  10.                 fmt.Print(i)  
  11.                 i++  
  12.                 fmt.Print(i)  
  13.                 i++  
  14.                 letter <- true  
  15.             }  
  16.         }  
  17.     }()  
  18.     // 打印字母
  19.     go func() {  
  20.         // 获得ASCII码  
  21.         i := 'A'  
  22.         for {  
  23.             if <-letter {  
  24.                 if i > 'Z' {  
  25.                     wait <- true  
  26.                     break  
  27.                 }  
  28.                 // 将ASCII码强转成字母输出  
  29.                 fmt.Print(string(i))  
  30.                 i++  
  31.                 fmt.Print(string(i))  
  32.                 i++  
  33.                 number <- true  
  34.             }  
  35.         }  
  36.     }()  
  37.     number <- true  
  38.     // 等待管道取值
  39.     <- wait
  40. }
复制代码
结尾

到此这篇关于GO利用channel协调协程的实现的文章就介绍到这了,更多相关GO  channel协调协程内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
1
精华
0
金钱
48
积分
13
注册时间
2022-12-21
最后登录
2023-1-29

发表于 2024-9-23 14:12:13 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:无名新人
  • 打卡总天数:2
  • 打卡月天数:0
  • 打卡总奖励:27
  • 最近打卡:2024-08-16 09:04:55
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
40
积分
6
注册时间
2023-11-9
最后登录
2024-8-16

发表于 2025-4-1 06:58:30 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表