我很高兴地宣布,我已经开始使用工作代码的有关并发设计模式的新系列。该播放列表将包含9-10个编码 +概念视频。有关完整的详细说明,请转到 codepiper youtube频道视频:https://youtu.be/eTJ7P0RCZJc
此博客将涵盖
- goroutines
- Waitgroup
- 频道
- 缓冲通道
- 并发僵局
goroutine:
Goroutines是GO中并发编程的基础(通常称为Golang)。它们是轻巧的,独立执行的功能,与同一地址空间中的其他goroutines同时运行。 Goroutines由GO运行时管理,他们通过一种称为“多路复用”的技术有效地利用了可用的CPU内核。您可以将Goroutine视为独立和同时运行其他功能的函数,从而可以在GO程序中有效且可扩展的并发。
func printNumbers() {
for i := 1; i <= 5; i++ {
fmt.Printf("%d ", i)
time.Sleep(100 * time.Millisecond)
}
}
func printLetters() {
for ch := 'a'; ch <= 'e'; ch++ {
fmt.Printf("%c ", ch)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go printNumbers() // Start a new Goroutine for printNumbers()
printLetters() // Execute printLetters() concurrently with the Goroutine
}
waitgroup:
WaitGroup是同步软件包中GO标准库提供的同步原始。它用于等待一系列Goroutines来完成执行,然后再在主要Goroutine中继续进行。当Goroutine完成任务时,候补组本质上是一个计数器,当启动并减少新的Goroutine时,它会增加。主goroutine可以在WaitGroup上调用WAIT,该Group将阻塞直到计数器变为零(即,所有Goroutines都完成了其任务并在WaitGroup上完成了任务)。它有助于协调多个goroutines的终止。
func printNumbers(wg *sync.WaitGroup) {
defer wg.Done() // Notify WaitGroup that this Goroutine is done when the function returns
for i := 1; i <= 5; i++ {
fmt.Printf("%d ", i)
time.Sleep(100 * time.Millisecond)
}
}
func printLetters(wg *sync.WaitGroup) {
defer wg.Done() // Notify WaitGroup that this Goroutine is done when the function returns
for ch := 'a'; ch <= 'e'; ch++ {
fmt.Printf("%c ", ch)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
var wg sync.WaitGroup
wg.Add(2) // Add the number of Goroutines to wait for
go printNumbers(&wg) // Start a new Goroutine for printNumbers()
go printLetters(&wg) // Start a new Goroutine for printLetters()
wg.Wait() // Wait until all Goroutines in the WaitGroup finish
fmt.Print("Okay you can go")
}
频道:
GO中的通道是一个打字导管,可以在不同的goroutines之间进行通信和同步。这是Goroutines向彼此发送和接收值的一种方式。渠道提供了一种安全的方式来交换数据并在Goroutines之间进行交流,防止种族条件和其他与并发有关的问题。通道可用于将数据从一个goroutine传递到另一个goroutine,从而有效地协调了并发任务。频道可以根据其容量而被禁止或缓冲。
func sender(ch chan<- int) {
for i := 1; i <= 10; i++ {
ch <- i // Send data to the channel
}
close(ch) // Close the channel after sending all data
}
func receiver(ch <-chan int) {
for num := range ch {
fmt.Printf("%d ", num) // Receive data from the channel
}
}
func main() {
ch := make(chan int)
go sender(ch) // Start a new Goroutine for the sender
receiver(ch) // Execute the receiver concurrently with the Goroutine
}
缓冲通道:
缓冲通道是GO中的一种类型的通道,具有固定能力容纳一定数量的元素。创建缓冲通道时,您将容量指定为制造功能的第二个参数。例如,ch:= make(chan int,10)。在这种情况下,CHUNCH CH最多可容纳10个元素。当Goroutine将值发送到缓冲通道时,如果有空间,它将被添加到通道的内部缓冲区中。如果通道已满,则发送Goroutine将阻塞直到缓冲区中有空间。同样,当Goroutine试图从缓冲通道接收值时,如果不是空的,它将从缓冲区接收数据。如果缓冲区为空,则接收goroutine将阻止直到数据可用。
func main() {
ch := make(chan int, 3) // Create a buffered channel with a capacity of 3
ch <- 1 // Send data to the channel
ch <- 2 // Send more data
ch <- 3 // Send even more data
// ch <- 4 // Sending a 4th value would cause a deadlock because the channel is full
fmt.Println(<-ch) // Receive data from the channel
fmt.Println(<-ch) // Receive more data
fmt.Println(<-ch) // Receive even more data
// fmt.Println(<-ch) // Receiving a 4th value would cause a deadlock because the channel is empty
}
注意:使用缓冲通道有时可以通过降低goroutines之间的争论来改善并发程序的性能,只要根据特定用例明智地选择缓冲区大小。但是,要注意缓冲尺寸以避免消耗过多的记忆。
func producer(ch chan<- int) {
for i := 1; i <= 5; i++ {
fmt.Printf("Producing %d\n", i)
ch <- i
time.Sleep(500 * time.Millisecond) // Simulate some work by the producer
}
close(ch)
}
func consumer(ch <-chan int) {
for num := range ch {
fmt.Printf("Consuming %d\n", num)
time.Sleep(1 * time.Second) // Simulate some work by the consumer
}
}
func main() {
normalCh := make(chan int) // Normal channel
bufferedCh := make(chan int, 3) // Buffered channel with capacity 3
fmt.Println("Using Normal Channel:")
go producer(normalCh)
consumer(normalCh)
time.Sleep(2 * time.Second) // Wait for the producer to finish
fmt.Println("\nUsing Buffered Channel:")
go producer(bufferedCh)
consumer(bufferedCh)
}
Using Normal Channel:
Producing 1
Consuming 1
Producing 2
Consuming 2
Producing 3
Consuming 3
Producing 4
Consuming 4
Producing 5
Consuming 5
Using Buffered Channel:
Producing 1
Consuming 1
Producing 2
Consuming 2
Producing 3
Producing 4
Consuming 3
Producing 5
Consuming 4
Consuming 5
YouTube频道:https://www.youtube.com/@codepiper
github链接:https://github.com/arshad404/CodePiper/tree/main/GO/concurrency-patterns/Basics