Golang 并發(fā)編程詳解
介紹
并發(fā)是現(xiàn)代軟件開(kāi)發(fā)中的一個(gè)重要概念,它允許程序同時(shí)執(zhí)行多個(gè)任務(wù),提高系統(tǒng)的性能和響應(yīng)能力。Golang 是一門天生支持并發(fā)的語(yǔ)言,它通過(guò) goroutine 和 channel 提供了強(qiáng)大的并發(fā)編程支持。
在本文中,我們將深入探討 Golang 中的并發(fā)編程,了解 goroutine、channel 以及一些常見(jiàn)的并發(fā)模式。
Goroutine
Goroutine 是 Golang 中的輕量級(jí)線程,由 Go 運(yùn)行時(shí)系統(tǒng)調(diào)度。它們比傳統(tǒng)的線程更輕便,創(chuàng)建和銷毀的代價(jià)更小,使得在程序中創(chuàng)建成千上萬(wàn)個(gè) goroutine 變得實(shí)際可行。
創(chuàng)建 Goroutine
在 Golang 中創(chuàng)建 goroutine 非常簡(jiǎn)單。只需在函數(shù)調(diào)用前使用關(guān)鍵字 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
函數(shù)被包裝成一個(gè) goroutine,并在 main
函數(shù)中異步執(zhí)行。time.Sleep(1 * time.Second)
用于等待足夠的時(shí)間,確保 printNumbers
有足夠的時(shí)間打印數(shù)字。注意,主 goroutine 并不會(huì)等待 printNumbers
執(zhí)行完畢。
Channel
Channel 是 Golang 中用于在 goroutine 之間傳遞數(shù)據(jù)的管道。它提供了一種同步的方式,確保數(shù)據(jù)安全地在 goroutine 之間傳遞。
創(chuàng)建 Channel
在 Golang 中,使用 make
函數(shù)創(chuàng)建 channel。
ch := make(chan int)
上述代碼創(chuàng)建了一個(gè)整數(shù)類型的無(wú)緩沖 channel。無(wú)緩沖 channel 在發(fā)送數(shù)據(jù)和接收數(shù)據(jù)時(shí)都會(huì)阻塞,直到另一方準(zhǔn)備好。
使用 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
將數(shù)字通過(guò) channel 發(fā)送給主 goroutine,并在發(fā)送完畢后關(guān)閉 channel。主 goroutine 使用 for num := range ch
循環(huán)接收 channel 中的數(shù)據(jù),直到 channel 被關(guān)閉。同時(shí),使用等待組(sync.WaitGroup
)確保所有 goroutine 執(zhí)行完畢后主 goroutine 才結(jié)束。
并發(fā)模式
除了簡(jiǎn)單的 goroutine 和 channel 的使用外,Golang 還提供了一些常見(jiàn)的并發(fā)模式,如等待組、互斥鎖等。這些模式幫助我們更好地組織和管理并發(fā)代碼。
等待組
等待組(WaitGroup)用于等待一組 goroutine 執(zhí)行完畢。它通過(guò)計(jì)數(shù)器實(shí)現(xiàn),每個(gè) goroutine 執(zhí)行前遞增計(jì)數(shù)器,執(zhí)行完畢后遞減計(jì)數(shù)器。主 goroutine 調(diào)用 Wait
方法等待計(jì)數(shù)器歸零。
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)用于保護(hù)共享資源,防止多個(gè) goroutine 同時(shí)訪問(wèn)導(dǎo)致的競(jìng)態(tài)條件。
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)
}
上述代碼中,兩個(gè) goroutine 并發(fā)地增加 counter
變量的值,使用互斥鎖 sync.Mutex
來(lái)保護(hù)臨界區(qū),確保同一時(shí)刻只有一個(gè) goroutine 能夠訪問(wèn)。
使用 Select 處理多 Channel
在一些場(chǎng)景中,我們可能需要同時(shí)處理多個(gè) channel,Golang 中提供了 select
語(yǔ)句來(lái)實(shí)現(xiàn)。
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
函數(shù)通過(guò) select
同時(shí)監(jiān)聽(tīng)兩個(gè) channel(ch1
和 ch2
),一旦其中一個(gè) channel 有數(shù)據(jù),就進(jìn)行處理。這種方式非常適用于處理多個(gè) channel 的情況。
結(jié)語(yǔ)
通過(guò)本文,我們深入了解了 Golang 中的并發(fā)編程,包括 goroutine、channel 以及一些常見(jiàn)的并發(fā)模式。并發(fā)編程使得 Golang 在處理高并發(fā)任務(wù)時(shí)表現(xiàn)出色,開(kāi)發(fā)者可以通過(guò)合理使用并發(fā)特性來(lái)提高程序性能。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-819408.html
希望讀者通過(guò)本文的學(xué)習(xí),能更好地應(yīng)用 Golang 中的并發(fā)編程,構(gòu)建高效、穩(wěn)定的軟件系統(tǒng)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-819408.html
到了這里,關(guān)于Golang 并發(fā)編程詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!