Golang 并发编程详解

这篇具有很好参考价值的文章主要介绍了Golang 并发编程详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Golang 并发编程详解

介绍

并发是现代软件开发中的一个重要概念,它允许程序同时执行多个任务,提高系统的性能和响应能力。Golang 是一门天生支持并发的语言,它通过 goroutine 和 channel 提供了强大的并发编程支持。

在本文中,我们将深入探讨 Golang 中的并发编程,了解 goroutine、channel 以及一些常见的并发模式。

Goroutine

Goroutine 是 Golang 中的轻量级线程,由 Go 运行时系统调度。它们比传统的线程更轻便,创建和销毁的代价更小,使得在程序中创建成千上万个 goroutine 变得实际可行。

创建 Goroutine

在 Golang 中创建 goroutine 非常简单。只需在函数调用前使用关键字 go 就可以将其包装成 goroutine。

package main

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

func printNumbers() {
	for i := 1; i <= 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Printf("%d ", i)
	}
}

func main() {
	go printNumbers()

	// 主 goroutine 不等待 printNumbers 完成
	time.Sleep(1 * time.Second)

	fmt.Println("Main goroutine")
}

上述代码中,printNumbers 函数被包装成一个 goroutine,并在 main 函数中异步执行。time.Sleep(1 * time.Second) 用于等待足够的时间,确保 printNumbers 有足够的时间打印数字。注意,主 goroutine 并不会等待 printNumbers 执行完毕。

Channel

Channel 是 Golang 中用于在 goroutine 之间传递数据的管道。它提供了一种同步的方式,确保数据安全地在 goroutine 之间传递。

创建 Channel

在 Golang 中,使用 make 函数创建 channel。

ch := make(chan int)

上述代码创建了一个整数类型的无缓冲 channel。无缓冲 channel 在发送数据和接收数据时都会阻塞,直到另一方准备好。

使用 Channel

package main

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

func printNumbers(ch chan int, wg *sync.WaitGroup) {
	defer wg.Done()

	for i := 1; i <= 5; i++ {
		time.Sleep(100 * time.Millisecond)
		ch <- i
	}
	close(ch)
}

func main() {
	ch := make(chan int)
	var wg sync.WaitGroup

	wg.Add(1)
	go printNumbers(ch, &wg)

	for num := range ch {
		fmt.Printf("%d ", num)
	}

	fmt.Println("Main goroutine")
	wg.Wait()
}

上述代码中,printNumbers 将数字通过 channel 发送给主 goroutine,并在发送完毕后关闭 channel。主 goroutine 使用 for num := range ch 循环接收 channel 中的数据,直到 channel 被关闭。同时,使用等待组(sync.WaitGroup)确保所有 goroutine 执行完毕后主 goroutine 才结束。

并发模式

除了简单的 goroutine 和 channel 的使用外,Golang 还提供了一些常见的并发模式,如等待组、互斥锁等。这些模式帮助我们更好地组织和管理并发代码。

等待组

等待组(WaitGroup)用于等待一组 goroutine 执行完毕。它通过计数器实现,每个 goroutine 执行前递增计数器,执行完毕后递减计数器。主 goroutine 调用 Wait 方法等待计数器归零。

package main

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

func printNumbers(wg *sync.WaitGroup) {
	defer wg.Done()

	for i := 1; i <= 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Printf("%d ", i)
	}
}

func main() {
	var wg sync.WaitGroup

	wg.Add(1)
	go printNumbers(&wg)

	wg.Wait()
	fmt.Println("Main goroutine")
}

互斥锁

互斥锁(Mutex)用于保护共享资源,防止多个 goroutine 同时访问导致的竞态条件。

package main

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

var counter = 0
var mutex sync.Mutex

func increment(wg *sync.WaitGroup) {
	defer wg.Done()

	for i := 0; i < 1000; i++ {
		mutex.Lock()
		counter++
		mutex.Unlock()
	}
}

func main() {
	var wg sync.WaitGroup

	wg.Add(2)
	go increment(&wg)
	go increment(&wg)

	wg.Wait()
	fmt.Printf("Final Counter: %d\n", counter)
}

上述代码中,两个 goroutine 并发地增加 counter 变量的值,使用互斥锁 sync.Mutex 来保护临界区,确保同一时刻只有一个 goroutine 能够访问。

使用 Select 处理多 Channel

在一些场景中,我们可能需要同时处理多个 channel,Golang 中提供了 select 语句来实现。

package main

import (
	"fmt"
	"time"
)

func producer(ch chan int, wg *sync.WaitGroup) {
	defer wg.Done()

	for i := 1; i <= 5; i++ {
		time.Sleep(100 * time.Millisecond)
		ch <- i
	}
	close(ch)
}

func consumer(ch1, ch2 chan int, wg *sync.WaitGroup) {
	defer wg.Done()

	for {
		select {
		case num, ok := <-ch1:
			if ok {
				fmt.Printf("From ch1: %d\n", num)
			}
		case num, ok := <-ch2:
			if ok {
				fmt.Printf("From ch2: %d\n", num)
			}
		}
	}
}

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	var wg sync.WaitGroup

	wg.Add(2)
	go producer(ch1, &wg)
	go producer(ch2, &wg)



	go consumer(ch1, ch2, &wg)

	wg.Wait()
	fmt.Println("Main goroutine")
}

上述代码中,consumer 函数通过 select 同时监听两个 channel(ch1ch2),一旦其中一个 channel 有数据,就进行处理。这种方式非常适用于处理多个 channel 的情况。

结语

通过本文,我们深入了解了 Golang 中的并发编程,包括 goroutine、channel 以及一些常见的并发模式。并发编程使得 Golang 在处理高并发任务时表现出色,开发者可以通过合理使用并发特性来提高程序性能。

希望读者通过本文的学习,能更好地应用 Golang 中的并发编程,构建高效、稳定的软件系统。文章来源地址https://www.toymoban.com/news/detail-819408.html

到了这里,关于Golang 并发编程详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Golang Channel详解:安全并发通信与避免死锁方法

    深入了解Golang中的Channel,探讨其线程安全性、类型特性以及避免死锁的方法。学习如何正确初始化、存取数据,关闭Channel以及处理只读只写情况。

    2024年02月10日
    浏览(50)
  • Golang单元测试与Goroutine详解 | 并发、MPG模式及CPU利用

    深入探讨Golang中单元测试方法及Goroutine的使用。了解并发与并行概念,MPG模式以及CPU相关函数的应用。解决协程并行中的资源竞争问题。

    2024年02月10日
    浏览(44)
  • Go语言(Golang)数据库编程

    要想连接到 SQL 数据库,首先需要加载目标数据库的驱动,驱动里面包含着于该数据库交互的逻辑。 sql.Open() 数据库驱动的名称 数据源名称 得到一个指向 sql.DB 这个 struct 的指针 sql.DB 是用来操作数据库的,它代表了0个或者多个底层连接的池,这些连接由sql 包来维护,sql 包会

    2024年02月03日
    浏览(93)
  • 【云原生 | 37】Docker快速部署编程语言Golang

    🍁 博主简介 :         🏅云计算领域优质创作者         🏅新星计划第三季python赛道第一名         🏅阿里云ACE认证高级工程师         🏅阿里云开发者社区专家博主 ✒️ 博主微信 :15575411187 💊 交流社区 :小鹏linux(个人社区)欢迎您的加入! 目录

    2024年02月01日
    浏览(64)
  • Golang vs Java: 一场编程语言的较量

    在IT行业飞速发展的过程中,编程语言扮演着至关重要的角色。作为开发人员,选择合适的编程语言对于构建高效、可靠和可维护的应用程序至关重要。在这场编程语言的较量中,Golang和Java无疑是两个备受青睐的选择。我们现在将对这两种语言进行全面对比,探讨它们在性能、简洁

    2024年04月17日
    浏览(57)
  • Golang vs Rust ——服务端编程应该选择哪种语言

    为服务端编程选择一种语言应该基于你的长期目标和项目的要求,因此,盲目地问我应该雇用 Go 开发人员还是应该选择 Rust 进行开发并不能帮助你解决问题。 然而,如果你发现自己陷入了困境,那么这篇文章将为你解惑。下面让我们开始吧。 Go 是一种静态类型的、AOT 编译的

    2024年02月02日
    浏览(62)
  • 【Golang星辰图】数据管理利器:Go编程语言中的数据库和搜索引擎综合指南

    Go编程语言是一种强大、类型安全且高效的编程语言,它在处理数据库和搜索引擎方面有着广泛的应用。本篇文章将详细介绍几个Go编程语言中常用的数据库和全文搜索引擎,包括Go-bleve、Go-pgx、Go-leveldb/leveldb、Go-xorm、Go-mysql-driver和Go-bbolt/bbolt。对于每个工具,我们将介绍其功

    2024年03月26日
    浏览(72)
  • golang并发安全-select

    前面说了golang的channel, 今天我们看看golang select 是怎么实现的。 select 非默认的case 中都是处理channel 的 接受和发送,所有scase 结构体中c是用来存储select 的case中使用的channel 编译器在中间代码生成期间会根据 select 中 case 的不同对控制语句进行优化,这一过程都发生在cmd/c

    2024年01月23日
    浏览(48)
  • golang 并发

    Golang 并发 并行 指的是在同一时刻 有多条指令在多个CPU处理器上同时执行 2个任务2个窗口需要硬件支持 并发是指在同一时刻 只能有一条指令 单多个进程指令快速轮换执行 2个队伍1个窗口 要求提升软件能力 Golang 并发优势 go 从底层就支持并发 简化了并发程序的编写方法 Go

    2024年02月03日
    浏览(36)
  • Golang 并发 Channel的用法

    上面是创建了无缓冲的 channel,一旦有 goroutine 往 channel 发送数据,那么当前的 goroutine 会被阻塞住,直到有其他的 goroutine 消费了 channel 里的数据,才能继续运行。 上面示例中的第二个参数表示 channel 可缓冲数据的容量。只要当前 channel 里的元素总数不大于这个可缓冲容量,

    2024年02月21日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包