Golang中有多少种并发控制方法? Go语言中的

发布于:2024-10-24 编辑:匿名 来源:网络

goroutine是一个轻量级的线程。其优点是占用资源少、切换成本低、能够高效实现并发操作。

但是如何控制这些并发的goroutine呢? 说到并发控制,首先想到的就是锁。 Go还提供了锁相关的机制,包括互斥锁sync.Mutex和读写锁sync.RWMutex;另外,Go还提供了原子操作sync/atomic。

但这些操作是为了并发进程中的数据安全,而不是为了goroutine本身。 本文主要介绍goroutine并发行为的控制。

Go 中最常用的方法有 3 个:sync.WaitGroup、channel 和 Context。 1.sync.WaitGroupsync.WaitGroup是Go语言中非常有用的同步原语。

它可以帮助我们等待一组 goroutine 完成。我们通常在以下场景中使用sync.WaitGroup:当我们需要在main函数中等待一组goroutine完成后再退出程序时。

当我们需要在一个函数中启动多个goroutine并确保它们全部完成后再返回结果时。当我们需要在一个函数中启动多个 goroutine 并确保它们全部完成后再执行操作时。

当我们需要在一个函数中启动多个 goroutine 并确保它们在关闭资源之前全部完成时。当我们需要在一个函数中启动多个 goroutine 并确保它们在退出循环之前全部完成时。

使用sync.WaitGroup时,我们需要首先创建一个sync.WaitGroup对象,然后使用其Add方法指定要等待的goroutines的数量。然后,我们可以使用 go 关键字来启动多个 Goroutine,并使用每个 Goroutine 中的sync.WaitGroup 对象的 Done 方法来指示该 Goroutine 已经完成。

最后,我们可以使用sync.WaitGroup对象的Wait方法来等待所有goroutines完成。下面是一个简单的例子,会启动三个goroutine,分别休眠0s、1s、2s。

这三个goroutine完成后main函数就会退出: 代码语言: go copy package mainimport ("fmt" "sync" "time" )func main() {var wgsync.WaitGroupfor i := 0;我<3; i++ {wg.Add(1)go func(i int) {defer wg.Done()fmt.Printf("子协程睡眠: %ds\n", i)time.Sleep(time.Duration(i) * time .Second)}(i)}wg.Wait()fmt.Println("主函数完成")}2. Go语言中的channel,使用channel可以帮助我们更好的控制goroutine的并发度。下面是一些常用的使用通道控制 Goroutine 并发的方法: 2.1 使用无缓冲通道进行同步 我们可以使用无缓冲通道来实现生产者-消费者模式,其中一个 Goroutine 负责生产数据,另一个 Goroutine 负责生产数据。

消耗数据。当生产者 Goroutine 向通道发送数据时,消费者 Goroutine 会阻塞等待数据到达。

这样我们就保证了生产者和消费者之间的数据同步。下面是一个简单的示例代码: 代码语言: go copy package mainimport ( "fmt" "sync" "time")func Producer(ch chan int, wg *sync.WaitGroup) { defer wg.Done() for i := 0;我<10; i++ { ch <- i fmt.Println("产生", i) time.Sleep(* time.Millisecond) } close(ch)}func Consumer(ch chan int, wg *sync.WaitGroup) { defer wg.Done( ) for i := range ch { fmt.Println("consumed", i) time.Sleep(* time.Millisecond) }}func main() { var wgsync.WaitGroup ch := make( chan int) wg.Add (2) go Producer(ch, &wg) go Consumer(ch, &wg) wg.Wait()} 在这个例子中,我们创建一个无缓冲的通道,用于生产者 Goroutine 和消费者 Goroutine 之间传递数据。

生产者 Goroutine 向通道发送数据,消费者 Goroutine 从通道接收数据。在生产者goroutine中,我们使用time.Sleep函数来模拟生产数据的时间。

在消费者goroutine中,我们使用time.Sleep函数来模拟消费数据的时间。最后,我们使用sync.WaitGroup来等待所有goroutine完成。

2.2 使用缓冲通道进行限流 我们可以使用缓冲通道来限制并发 goroutine 的数量。在这种情况下,我们可以将通道的容量设置为我们想要的并发 goroutine 的最大数量。

然后,在启动每个 goroutine 之前,我们向通道发送一个值。 Goroutine 完成后,我们从通道接收一个值。

这样我们就可以保证同时运行的goroutine数量不超过我们指定的最大并发数。下面是一个简单的示例代码: 代码语言: go copy package mainimport ("fmt" "sync")func main() { var wgsync.WaitGroup maxConcurrency := 3 semaphore := make(chan struct{}, maxConcurrency) for我:= 0;我<10; i++ { wg.Add(1) go func() { defer wg.Done() 信号量 <- struct{}{} fmt.Println("goroutine", i, "started") // 做一些工作 fmt.Println( "goroutine", i, "finished") <-semaphore }() } wg.Wait()} 在这个例子中,我们创建了一个缓冲区大小为 3 的缓冲通道。

然后,我们启动了 10 个 goroutine。在每个 goroutine 中,我们向通道发送一个空结构,表示该 goroutine 已经开始执行。

Goroutine 完成后,我们从通道收到一个空结构,表明 Goroutine 已完成执行。这样我们就可以保证同时运行的goroutine数量不超过3个。

3. Context 在Go语言中,使用Context可以帮助我们更好的控制goroutine的并发度。下面是一些常用的使用 Context 来控制 goroutine 并发的方法: 3.1 超时控制 在某些情况下,我们需要限制 goroutine 的执行时间,以避免程序长期阻塞或者死锁等问题。

使用Context可以帮助我们更好的控制goroutine的执行时间。我们可以创建一个带有超时的 Context 并将其传递给 goroutine。

如果goroutine在超时时间内没有完成执行,我们可以使用Context的Done方法来取消goroutine的执行。下面是一个简单的示例代码: 代码语言: go copy package mainimport ( "context" "fmt" "time")func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.其次) defer cancel() go func() { for { select { case <-ctx.Done(): fmt.Println("goroutine finish") return default: fmt.Println("goroutine running") time.Sleep(* time.Millisecond) } } }() time.Sleep(3 * time.Second)} 在此示例中,我们创建一个带有超时的 Context,然后将其传递给 goroutine。

在goroutine中,我们使用select语句来监听Context的Done方法。如果 Context 超时,我们将取消 goroutine 的执行。

3.2 取消操作 在某些情况下,我们需要在程序运行时取消某些goroutine的执行。使用Context可以帮助我们更好的控制goroutine的取消操作。

我们可以创建一个具有取消功能的 Context 并将其传递给 goroutine。如果我们需要取消goroutine的执行,可以使用Context的Cancel方法来取消goroutine的执行。

下面是一个简单的示例代码: 代码语言: go copy package mainimport ( "context" "fmt" "sync" "time")func main() { ctx, cancel := context.WithCancel(context.Background()) var wgs??ync.WaitGroup wg.Add(1) go func() { defer wg.Done() for { select { case <-ctx.Done(): fmt.Println("goroutine finish") return default: fmt.Println( "goroutine running") time.Sleep(* time.Millisecond) } } }() time.Sleep(2 * time.Second) cancel() wg.Wait()} 在这个例子中,我们创建了一个函数的上下文,然后传递给 goroutine。在goroutine中,我们使用select语句来监听Context的Done方法。

如果 Context 被取消,我们就会取消 goroutine 的执行。在main函数中,我们使用time.Sleep函数来模拟程序运行过程中某个时刻需要取消goroutine的执行,然后调用Context的Cancel方法来取消goroutine的执行。

3.3 资源管理 在某些情况下,我们需要对 goroutine 使用的资源进行管理,以避免资源泄漏或竞争条件等问题。使用Context可以帮助我们更好的管理goroutine使用的资源。

我们可以将资源与Context关联起来,然后将Context传递给goroutine。当goroutine执行完成后,我们可以使用Context来释放资源或者进行其他资源管理操作。

下面是一个简单的示例代码: 代码语言: go copy package mainimport ( "context" "fmt" "sync" "time")func worker(ctx context.Context, wg *sync.WaitGroup) { defer wg.Done() for { select { case <-ctx.Done(): fmt.Println("goroutine finish") return default: fmt.Println("goroutine running") time.Sleep(* time.Millisecond) } }}func main() { ctx, cancel := context.WithCancel(context.Background()) var wgsync.WaitGroup wg.Add(1) go worker(ctx, &wg) time.Sleep(2 * time.Second) cancel() wg.Wait ()} 在此示例中,我们创建一个具有取消功能的 Context,然后将其传递给 goroutine。在goroutine中,我们使用select语句来监听Context的Done方法。

如果 Context 被取消,我们就会取消 goroutine 的执行。在main函数中,我们使用time.Sleep函数来模拟程序运行过程中某个时刻需要取消goroutine的执行,然后调用Context的Cancel方法来取消goroutine的执行。

我正在参加第五期腾讯科技创造特训营有奖征文比赛。快来和我分享奖品吧!免责声明:本作品根据 Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) 许可证获得许可。

使用时请注明来源。

Golang中有多少种并发控制方法? Go语言中的

站长声明

版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。

标签:

相关文章

  • 一夜之间,又有两家独角兽取消IPO

    一夜之间,又有两家独角兽取消IPO

    昨晚(3月11日),在发行人和保荐人的倡议下,上交所暂停了依图科技科创板上市申请的审核。 无独有偶,由于发行人撤回发行上市申请或保荐机构撤回保荐,上交所决定终止对禾赛科技首次公开发行股票并在科创板上市的审核。 这并不是一个孤立的案例。 上个月,独角兽孔夫子也因主

    06-18

  • Pika 6 个月估值 2 亿美元,斯坦福华人博士出品

    Pika 6 个月估值 2 亿美元,斯坦福华人博士出品

    用一句话拍一部电影听起来像是一个幻想——现在,风靡硅谷的 Pika 1.0 让这成为可能。 今天,美国人工智能初创公司Pika Labs发布了文生视频新产品Pika 1.0。 使用Pika 1.0制作视频几乎没有门槛——用户只需要输入一句话就可以生成你想要的各种风格的视频,并通过简单的描述来

    06-18

  • 专注敏感数据访问控制,“中图吉人”完成线性资本领投的数千万元Pre-A轮融资

    专注敏感数据访问控制,“中图吉人”完成线性资本领投的数千万元Pre-A轮融资

    投资界动态(ID:pedaily)9月15日消息,专注敏感数据访问控制安防厂商“看图识人”近日完成数千万元Pre-A轮融资。 据介绍,本轮融资由线性资本领投,驰星创投跟投,航程资本提供财务顾问服务。 中图世人成立于今年11月,目前专注于敏感数据访问控制,目标是将每个数字身份与

    06-18

  • 无人驾驶技术公司白犀牛宣布获得近千万美元Pre-A融资,线性资本领投

    无人驾驶技术公司白犀牛宣布获得近千万美元Pre-A融资,线性资本领投

    自动驾驶科技公司白犀牛宣布获得近千万美元Pre-A轮融资,由线性资本领投。 2019年7月,白犀牛宣布获得线性资本领投的近千万美元Pre-A轮融资。

    06-18

  • 为加速充电新国标落地,特斯拉启动充电合作伙伴计划

    为加速充电新国标落地,特斯拉启动充电合作伙伴计划

    去年12月,国家质量监督检验检疫总局、国家标准局、国家能源局、工信部国家信息化部、科技部等部门联合发布了新修订的电动汽车充电接口和通信协议五项国家标准,对充电安全性和兼容性提出了明确的技术要求,以解决充电问题。 但实际情况是,目前企业对车桩升级改造的意愿和效

    06-18

  • 一个时代结束了!谷歌“教父”埃里克·施密特离开公司:他是如何建立谷歌帝国的?

    一个时代结束了!谷歌“教父”埃里克·施密特离开公司:他是如何建立谷歌帝国的?

    长江后浪推前浪,但后浪也需要前浪的引导。 在谷歌20多年的发展趋势中,埃里克施密特就是这样的先驱者。 作为职业经理人,他深度参与了谷歌从一家硅谷初创公司到全球科技巨头Alphabet的整个发展过程。 他与谷歌两位创始人并称为“谷歌三巨头”。 可以说,埃里克施密特是当之无

    06-18

  • 理想汽车发布2021年第二季度财报,营收达50.4亿元

    理想汽车发布2021年第二季度财报,营收达50.4亿元

    理想汽车今日发布2021年第二季度财报。 财报显示,理想汽车第二季度营收达50.4亿元。

    06-18

  • 新浪读书获4000万天使轮融资

    新浪读书获4000万天使轮融资

    据投资界8月25日消息,据36氪报道,北京新浪读书信息技术有限公司(以下简称“新浪读书”)近期完成万家融资天使轮融资,由华盛顿智慧、创始人团队等投资,象屿资本担任财务顾问独家投资。 新浪读书是一个互联网出版平台。 该项目最初是基于“新浪读书”推出的。 2008年起独

    06-17

  • TikTok回应安全担忧:美国用户数据存储在美国

    TikTok回应安全担忧:美国用户数据存储在美国

    语音播放文章内容 深声科技提供技术支持 您的浏览器不支持音频元素。 据雷锋网报道,近日,TikTok(抖音海外版)在其官网发表文章,就内容审查、数据安全等方面回应美国议员提出的质疑。 TikTok 表示,它不受任何政府的影响。 自2017年上线以来,TikTok在海外市场取得了巨大成

    06-18

  • 规模超百亿,成都多个重点产业链项目基金已签约

    规模超百亿,成都多个重点产业链项目基金已签约

    投资界(ID:pedaily)消息,11月22日,中国主办成都市人民政府、成都市地方金融监督管理局。 资本创新(成都)峰会在天府国际会议中心正式拉开帷幕。 会上,多个成都重点产业链“建圈强链”项目资金签约。 成都重点产业链“建圈强链”项目基金落地签约仪式 据悉,该批项目基

    06-17

  • 烘焙品牌“花木子”获数百万元天使轮+融资,齐光资本、中林资本投资

    烘焙品牌“花木子”获数百万元天使轮+融资,齐光资本、中林资本投资

    投资圈(ID:pedaily)8月5日消息,“花木子”获数百万元天使轮融资+ 融资,齐光资本跟投,中林资本跟投。 本轮资金将用于新产品研发、品牌推广和渠道拓展。 花木子成立于今年3月。 以早餐场景为切入点,推出了肉松芝士吐司、芝士岩烤吐司、牛角面包、绿豆糕等产品。 爆款松丝

    06-18

  • 欧盟高官:欧盟和欧洲央行正准备退出紧急计划

    欧盟高官:欧盟和欧洲央行正准备退出紧急计划

    北京时间5月18日晚间消息,据外电报道,欧盟贸易代表卡雷尔德古赫特今天表示,欧盟委员会欧洲央行正在制定紧急计划,以防希腊退出欧元区。   据路透社报道,虽然近期希腊退出欧元区的传闻甚嚣尘上,但欧盟高级官员在接受报纸采访时发表此类言论尚属首次。 这是他首次承认正

    06-18