Go中按次序交替打印1212...,你知道它背后的设计模式吗

(Go语言)使用两个协程按顺序交替打印 1 - n ,一个协程打印偶数,一个协程打印奇数 Go语言中使用两个协程按顺序交替打印 1 - n ,一个协程打印偶数,一个协程打印奇数。 阅读详情

聊聊后端面试那些事

原文

让你goroutine交替打印1212…-[公粽号:堆栈future]

首先这道题看似是两个goroutine交替打印,实则是有很多细节需要考虑,而且背后的设计模式就是生产者消费者模式。

代码演示下简单的生产者消费者模式:

package main

import "fmt"

func main() {
 done := make(chan bool) //控制结束退出的信号
 ch := make(chan int) //chan通信 控制同步阻塞的

 go func() {
  for i:=1; i<=2; i++ {
   //生产
   ch <- 0
   fmt.Println("1")
  }

  //发送结束之后退出
  done <- true
 }()

 go func() {
  for i:=1; i<=2; i++ {
   //消费
   <- ch
   fmt.Println("2")
  }
 }()
 <-done
}

输出:
1
1
2
2

但是题目是让两个goroutine交替输出1212…而且还必须保证次序,比如A goroutine是永远打印1,B goroutine永远打印2 这样循环2次,输出结果应该是1212。

那么为什么上面的代码输出是1122呢?因为我们控制了开始的次序,但是并没有控制结束的次序,发生了并发不安全的情况。

当然你不能说这种方式就不适合别的场景,比如交替打印奇偶数,就增加一个条件判断就行:

package main

import "fmt"

func main() {
 done := make(chan bool) //控制结束退出的信号
 ch := make(chan int) //chan通信 控制同步阻塞的

 go func() {
  for i:=1; i<=5; i++ {
   //生产
   ch <- 0
   if i % 2 == 0 {
    fmt.Println("A ", i)
   }
  }

  //发送结束之后退出
  done <- true
 }()

 go func() {
  for i:=1; i<=5; i++ {
   //消费
   <- ch
   if i % 2 != 0 {
    fmt.Println("B ", i)
   }
  }
 }()
 <-done
}

输出:
B  1
A  2
B  3
A  4

B永远输出奇数,A永远输出偶数,它们交替打印。

好了言归正传,那我们如何写出并发安全的生产者消费者代码呢?我们用首尾两个chan交替释放控制权就可以解决这个问题,请看代码:

package main

import "fmt"

func main() {
 done := make(chan bool) //控制结束退出的信号
 chStart := make(chan int) //chan通信 控制起始同步阻塞的
 chEnd := make(chan int) //chan通信 控制结尾同步阻塞的

 go func() {
  for i:=1; i<=2; i++ {
   //生产 控制起始
   chStart <- 0
   fmt.Println("A ", 1)
   //暂停 等待结尾信号
   <-chEnd
  }

  //发送结束之后退出
  done <- true
 }()

 go func() {
  for i:=1; i<=2; i++ {
   //消费 结束起始
   <- chStart
   fmt.Println("B ", 2)

   //发送结尾信号
   chEnd <- 0
  }
 }()
 
 //阻塞等待退出信号
 <-done
}

输出:
A  1
B  2
A  1
B  2

现在可以看出来,输出的结果是正确的。为什么这么操作呢?就是当生产者生产之后把自己阻塞,等待消费者消费,消费者消费完成之后发送信号唤醒生产者继续生产,而消费者自己又被阻塞等生产者唤醒,其实这就是典型的生产者消费者模式。

小结

用两个chan实现按次序交替非常有意思,它背后的设计模式生产者消费者模式,大家可以在项目中使用起来,如果你觉得这篇文章对你有帮助,欢迎关注点赞转发哦。

- END -

公粽号:堆栈future

使很多处于迷茫阶段的coder能从这里找到光明,堆栈创世,功在当代,利在千秋

图片

go 实现数字字母交替打印并优雅关闭channel 这个效果其实有很多种写法,现在选取一个简单的写法,通常的写法是让两个协程交替打印,用chan来阻塞通知,但是由于大部分的demo都没有考虑优雅退出的问题,这次的demo添加了一个stopCha来优雅退出并close通道。 阅读详情

相关推荐

golang实现奇数偶数交替输出(生产者消费者模型)

作业题如下: 假设存在一个生产者,依次产生数字0到9。存在一个奇数消费者,一个偶数消费者分别使用奇数和偶数,使用Go语言通道实现这个生产者消费者模型的代码如下: package main import ( "fmt" "sync" ) var wg sync.WaitGroup func producer(odd chan<- int, even chan<- int) { defer wg.Done() for i := 0; i < 10; i++ { if i

son_king的博客 1065

Golang: 三个goroutines轮流打印1-20之内的数字

用channels来协调goroutines之间的运行顺序。

qq_43642136的博客 555

Golang 面试题(3) 两个协程轮流打印字母和数字

Golang面试编程题3 实现两个协程轮流输出A 1 B 2 C 3 .... Z 26 方案1:有缓冲的chan func ChannelFunc() { // 思想:两个g,一个输出数字,一个输出字母,重点是如何控制两个g的打印顺序,让其可以轮流打印 // 分别使用两个缓存为1的chan,来控制两个g的打印顺序 strChan := make(chan int, 1) numCha...

Y先森0.0 2115

go实现交替输出

有两个协程,协程1输出 1-10 , 协程2输出 A-J, 要求两个协程交替输出,输出示例为1 A 2 B 3 C 4 D...,输出完毕后程序结束运行。

fusugongzi的博客 396

区块链技术在碳足迹数据存证与溯源中的应用深度解析

消费者扫描产品上的二维码,即可通过区块链浏览器查询到该产品的数字碳标签,并追溯其从茶园到货架的每一步碳足迹数据,以及这些数据是如何被智能合约自动计算和认证的,从而建立起强大的品牌信任。如果说哈希链解决了数据的“存”与“证”的问题,那么智能合约则解决了数据“用”与“管”的自动化问题。综上所述,虽然针对“碳足迹数据可追溯性”这一特定应用场景的公开、标准化的性能基准案例尚不丰富,但现有研究和企业级解决方案(特别是联盟链)已经证明,通过合理的技术选型和架构设计,区块链的性能可以满足实际商业需求。

百态·数智思维 | 聚焦大数据、量化与未来AI 1106

基于步科(Kinco HMI 2.5)的组态软件使用

本篇介绍Kinco HMI 2.5的组态软件使用,图标如下 目录   一、新建工程并配置连接 1.1 根据工程选择PLC与HMI型号 1.2 配置PLC连接与选项 二、组态画面编辑 2.1 打开画面窗口 2.2 编辑画面 2.3 组态变量与PLC程序变量连接 三、组态程序下载到HMI 3.1 连接 3.2 编译 3.3 下载 一、新建工程并配置连接 1.1 根据工...

ACanswer的专栏 1万+

Golang多协程利用chan交替打印奇数和偶数

Golang多协程(goroutine)利用chan交替打印奇数和偶数

即心即佛 2272

224G PAM-4 通道的 PCB 和封装设计

该行业正在努力实现层厚非常低的 sub-Dk = 3 材料,以及更先进的加工,这将使封装和 PCB 中的透射电镜截止值更高。当回波损耗占主导地位时,我们基本上需要去除沿互连产生阻抗失配的任何元件,就像上面描述的更光滑的铜和更低的 Dk 值一样。第二个影响是传输线阻抗匹配在 56 GHz 范围内的非常高的频率下非常困难的主要原因之一,另一个因素是 Tx 或 Rx 封装/缓冲器中的寄生效应。由于 PCB 和封装中的长度刻度,这是 BGA 上的焊盘、过孔和球等小结构开始在输入阻抗中产生明显偏差的频率范围。

jkh920184196的博客 840

【go】 面试题:多线程打印1-10 并要求顺序保证?

1 答案: package main import ( "fmt" "sync/atomic" "time" ) func main() { var count uint32 trigger := func(i uint32, fn func()){ for{ if n := atomic.LoadUint32(&count); n == i { fn() .

qfzhangwei的专栏 1124

Windows Server 2008 R2装不上VMware Tools?别急,手动安装驱动补丁的保姆级教程来了

本文提供了Windows Server 2008 R2手动安装VMware Tools驱动补丁的详细教程,解决驱动签名验证失败问题。通过获取特定补丁文件、创建安装介质、挂载虚拟机并安装补丁等步骤,帮助用户顺利完成VMware Tools安装,提升虚拟机功能与性能。

weixin_28335283的博客 467

逆变器技术解析:DDSRF双解耦在正负序分离中的关键作用

本文深入解析了DDSRF双解耦技术在逆变器正负序分离中的关键作用。通过建立正反旋转坐标系并利用交叉反馈解耦网络,DDSRF能快速、精准地分离电网电压中的正负序分量,从而显著提升锁相环在电网不平衡条件下的精度与系统稳定性,是现代高性能并网逆变器的核心算法之一。

m3n5b7v8c9x的博客 409

Goroutine交替执行的相关问题与方法

多个Goroutine交替执行输出 文章目录多个Goroutine交替执行输出两个协程交替打印1-100的奇偶数使用channel作为信号传递实现使用runtime让协程竞争CPU使用sync的锁竞争实现N个线程交替打印0-100没有严格的交替顺序的时候有严格交替顺序的时候channel实现线程池参考资料 Go语言的协程goroutine在高并发方面具有优势,最简单的可以写一个简单的生产者消费者模型。 func mode1() { rand.Seed(time.Now().UnixNano()) wg

m0_60647847的博客 1905

李宏毅机器学习hw3

Homework 3 - Convolutional Neural Network 1作业概述 在food_11文件中有三个文件分别是training、validation、testing,打开training和validation可以看见总共有11种食物(0-10的类别编号),而testing是没有类别编号的。 然后用卷积神经网络对食物图片进行分类。 2导入用到的库 torch库 这个我弄了半天,直接pip总是timeout,用镜像源下下来又出现OSError: [WinError..

老问题的博客 4187

使用golang中goroutine顺序打印a,b,c N次

可以使用golang中的chan来相互通知,然后使用sync/Waitgroup来等待goroutine完成执行结束。该问题中主要考虑的是golang中goroutine的基本能使用,如何控制顺序调用。

qq_45061361的博客 573

“华为杯”研究生数学建模竞赛2016年-【华为杯】A题:多无人机协同任务规划

题分别求解,保证了攻击方无人机滞留在防御方雷达有效探测范围内的时间总和最小,接着,通过提出巡检待命无人机的设想,型无人机携带炸弹的具体清单和攻击的目标清单),保证攻击方的无人机滞留防御方雷。在使用基于贪心算法的覆盖法时,覆盖的目标点中必须首先不含配备雷达站的目标点。步优化保证攻击方的无人机滞留防御方雷达有效探测范围内的时间总和最小,需首先。的“灵巧”炸弹,采用抛投方式对地攻击,即投放后炸弹以飞机投弹时的速度作抛物。运动,当炸弹接近目标后,可主动寻的攻击待打击的目标,因此炸弹落点位于目标中。

getusushu的博客 1034

http协议

HTTP 协议由起始行、头部、空行、消息体组成。

qq_34059233的博客 88

Golang俩个线程实现交替打印1和2 10次

一、一个进程写,一个进程读, 一个管道存数据, 一个管道进行退出控制。 func main() { intChan := make(chan int, 20) exitChan := make(chan bool, 1) go func(intChan chan int){ for i:=0; i< 20; i++ { intChan<- (i%2 + 1) ...

Lin_junhan的博客 1674

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Go并发多协程顺序打印

启动三个协程分别打印1、2、3,要求按照123123123123……的顺序打印出来,可以使用锁或者通道实现。也可以用通道实现,channel分为有缓冲和无缓冲,内部封装了锁,读写通道是原子性的;有缓冲通道:发送会在缓冲区未满时不阻塞,在缓冲区满时阻塞。无缓冲通道 :发送和接收都会阻塞,直到被接收或者通道有值。

笔记 852

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

golang协程顺序打印0-100

【代码】golang协程顺序打印0-100。

just_so_so_fnc的博客 1967

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

golang学习笔记——面试题 使用 3 个协程顺序打印 cat、dog、fish 各 100 次

思考,可否换成无缓冲区的 channel。

mirana的专栏 2149

使用两个go协程顺序打印一个字符串

使用两个go协程顺序打印一个字符串

wgchen 502

Go语言交替打印问题及多种实现方法

Go语言交替打印问题详解

weixin_52242569的博客 794

[Goroutine]使用多协程并发地按照顺序打印字母表

theme: channing-cyan 今天分享一道非常经典的并发问题,使用多个协程按照顺序打印字母表的字母,每个打印 10 次。 思路:显然这里是要我们管道和协程完成同步交替打印,先把问题缩小,思考三个协程打印 a、b、c 的情形。最直接的思路就是定义三个管道,第 1 个协程打印完之后之后通知下一个协程,最后一个协程打印完成之后通知第 1 个协程继续打印,从而形成一个环。 代码如下:...

weixin_45254062的博客 560

【go每日一题】 无缓冲chan作为锁,多协程顺序打印数字

其实这样的题目没什么实际意义,如果要多协程竞争锁打印数字,还要顺序,那还不如一个协程把所有事情处理完毕,多协程一般用来做并行操作。如果将题目变为:多协程,顺序打印1-20,每个协程需要轮流打印呢?多协程顺序打印 1-20数字。

YiGeiGiaoGiao的博客 522

Go多个协程实现顺序打印

【代码】Go多个协程实现顺序打印。

a_jie_2016_05的博客 398

Golang面试题: 3个goroutine交替打印ABC

文章目录题目介绍做法一题目扩展 开心一刻        一位小帅哥和靓姑娘在火车上相遇。经过一阵“天南地北,生猛海鲜”之后,小帅哥拿出一副扑克与姑娘对玩:   帅哥:QQK?(谈谈看)   姑娘:Q45?(谈什么)   帅哥:Q21!(谈恋爱)   姑娘:8Q!!(不谈)   $%……!   快到站了,小帅哥不甘心,又拿出扑克:   帅哥:3QQK?(再谈谈看)   姑娘:948Q!!!(就是不谈)   帅哥:—%¥……) 题目介绍     &nb

xingyu97的博客 4224
上一篇: k8s两种部署架构,你们是哪一种?为什么面试官会问你你们怎么部署微服务的呢?
下一篇: Nacos服务注册和发现以及配置管理技术分享,Go中接入非常简单极易上手
stackfuture
博客等级 码龄5年 23粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值