偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

每個(gè) Go 開發(fā)者都應(yīng)該知道的 goroutine 模式

開發(fā) 后端
本文讓我們深入了解 Go 中的主要并發(fā)概念,包括它們的定義、示例、優(yōu)勢(shì)以及有效使用的技巧。

Go 是為并發(fā)編程而設(shè)計(jì)的。它輕量、高效,并簡(jiǎn)化了創(chuàng)建并行應(yīng)用程序的過程,內(nèi)置支持 goroutine 和通道。讓我們深入了解 Go 中的主要并發(fā)概念,包括它們的定義、示例、優(yōu)勢(shì)以及有效使用的技巧。

Goroutines

goroutine 是由 Go 運(yùn)行時(shí)調(diào)度的輕量級(jí)線程,創(chuàng)建成本遠(yuǎn)低于操作系統(tǒng)線程,可在單一進(jìn)程中啟動(dòng)成千上萬的并發(fā)任務(wù)。

package main

import (
    "fmt"
    "time"
)

func printNumbers() {
    for i := 1; i <= 5; i++ {
        fmt.Println(i)
        time.Sleep(500 * time.Millisecond)
    }
}

func main() {
    go printNumbers()
    fmt.Println("Goroutine started!")
    time.Sleep(3 * time.Second)
}

優(yōu)勢(shì):

  • 極低內(nèi)存占用,適合 I/O 密集或需大量等待的任務(wù)
  • 自動(dòng)調(diào)度,充分利用多核處理器

通道(channel)

通道是一種類型安全的通信機(jī)制,用于在 goroutine 之間傳遞數(shù)據(jù)并確保同步。

package main

import "fmt"

func sum(nums []int, resultChan chan int) {
    sum := 0
    for _, num := range nums {
        sum += num
    }
    resultChan <- sum
}

func main() {
    nums := []int{1, 2, 3, 4, 5}
    resultChan := make(chan int)
    go sum(nums, resultChan)
    result := <-resultChan
    fmt.Println("Sum:", result)
}

優(yōu)點(diǎn):通道提供了一種強(qiáng)大的方式來同步數(shù)據(jù)傳輸,簡(jiǎn)化了通信并防止數(shù)據(jù)競(jìng)爭(zhēng)。通過確保數(shù)據(jù)僅在準(zhǔn)備好時(shí)發(fā)送或接收,通道有助于避免典型的同步問題。

Channel Axioms

Channel Axioms 定義了通道行為的規(guī)則:

  • 對(duì)無緩沖通道,發(fā)送與接收雙方在對(duì)方就緒前均會(huì)阻塞。
  • 關(guān)閉通道后不可再發(fā)送數(shù)據(jù),違者將觸發(fā) panic。
package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    close(ch)

    for val := range ch {
        fmt.Println(val)
    }
}

優(yōu)點(diǎn):理解 Channel Axioms 有助于避免在 Go 中常見的陷阱,如死鎖和競(jìng)爭(zhēng)條件。通過了解阻塞和關(guān)閉通道的工作原理,開發(fā)人員可以設(shè)計(jì)出可靠的并發(fā)應(yīng)用程序。

基于通道的錯(cuò)誤處理

在使用通道時(shí),處理可能發(fā)生的錯(cuò)誤至關(guān)重要,尤其是在多個(gè) goroutine 共享數(shù)據(jù)或資源時(shí)。

package main

import (
    "errors"
    "fmt"
)

func divide(dividend, divisor int, resultChan chan int, errorChan chan error) {
    if divisor == 0 {
        errorChan <- errors.New("cannot divide by zero")
        return
    }
    resultChan <- dividend / divisor
}

func main() {
    resultChan := make(chan int)
    errorChan := make(chan error)
    go divide(10, 0, resultChan, errorChan)

    select {
    case result := <-resultChan:
        fmt.Println("Result:", result)
    case err := <-errorChan:
        fmt.Println("Error:", err)
    }
}

優(yōu)點(diǎn):基于通道的錯(cuò)誤處理使得對(duì)并發(fā)任務(wù)的細(xì)粒度控制成為可能,使程序能夠有效地管理和響應(yīng)錯(cuò)誤。

選擇語(yǔ)句

select 允許 goroutine 同時(shí)等待多個(gè)通信操作,先就緒者先執(zhí)行。

package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)

    go func() {
        time.Sleep(1 * time.Second)
        ch1 <- "from channel 1"
    }()
    go func() {
        time.Sleep(2 * time.Second)
        ch2 <- "from channel 2"
    }()

    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    case msg2 := <-ch2:
        fmt.Println(msg2)
    }
}

優(yōu)點(diǎn):select 使非阻塞并發(fā)成為可能,程序可以在不等待所有通道的情況下繼續(xù)執(zhí)行,從而提高響應(yīng)速度。

使用 WaitGroups 協(xié)調(diào)并發(fā)

sync.WaitGroup 有助于管理多個(gè) goroutine,確保它們?cè)诔绦蚶^續(xù)執(zhí)行之前全部完成。

package main

import (
    "fmt"
    "sync"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d starting\n", id)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    var wg sync.WaitGroup
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }
    wg.Wait()
    fmt.Println("All workers done")
}

優(yōu)點(diǎn):WaitGroups 提供了一種簡(jiǎn)單的方法來協(xié)調(diào) goroutines,確保適當(dāng)?shù)耐讲⒎乐钩绦蜻^早退出。

上下文包(Context)

Go 中的context包對(duì)于管理 goroutine 的生命周期非常有用,特別是在取消、截止日期和超時(shí)方面。

package main

import (
    "context"
    "fmt"
    "time"
)

func work(ctx context.Context) {
    select {
        case <-time.After(5 * time.Second):
        fmt.Println("Work completed")
        case <-ctx.Done():
        fmt.Println("Work canceled")
    }
}

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    go work(ctx)
    time.Sleep(3 * time.Second)
}

優(yōu)點(diǎn):上下文對(duì)于管理具有眾多 goroutine 的復(fù)雜應(yīng)用程序是無價(jià)的,提供了一種結(jié)構(gòu)化的方式來處理取消、截止日期和層次結(jié)構(gòu)。

扇出和扇入(Fan-Out / Fan-In)

在扇出/扇入模式中,任務(wù)被分配到多個(gè) goroutine 中,并聚集回一個(gè)中央 goroutine。

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func worker(id int, out chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
    out <- id
}

func main() {
    out := make(chan int, 5)
    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i, out, &wg)
    }

    go func() {
        wg.Wait()
        close(out)
    }()

    for result := range out {
        fmt.Println("Result:", result)
    }
}

優(yōu)點(diǎn):Fan-In/Fan-Out 最大化并發(fā)性,非常適合數(shù)據(jù)處理任務(wù)或多個(gè) goroutine 執(zhí)行反饋到中心過程的子任務(wù)的情況。

資源池:sync.Pool

sync.Pool 通過池化可重用資源來幫助管理,從而減少內(nèi)存分配的負(fù)擔(dān)。

package main

import (
    "fmt"
    "sync"
)

func main() {
    pool := sync.Pool{
        New: func() interface{} {
            return "new"
        },
    }

    pool.Put("first")
    fmt.Println(pool.Get())
    fmt.Println(pool.Get())
}

優(yōu)點(diǎn):減少垃圾收集并改善內(nèi)存管理,尤其在高負(fù)載或頻繁訪問的資源中非常有用。

單次初始化:sync.Once

sync.Once 結(jié)構(gòu)確保一個(gè)函數(shù)只執(zhí)行一次,無論有多少個(gè) goroutine 嘗試調(diào)用它。

package main

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

var once sync.Once

func initialize() {
    fmt.Println("Initialization done")
}

func main() {
    for i := 0; i < 3; i++ {
        go once.Do(initialize)
    }
    time.Sleep(1 * time.Second)
}

優(yōu)點(diǎn):有助于資源初始化,這種初始化只應(yīng)發(fā)生一次,防止冗余設(shè)置并確保線程安全。

數(shù)據(jù)競(jìng)爭(zhēng)與互斥

當(dāng)兩個(gè) goroutine 同時(shí)訪問同一個(gè)變量,其中至少一個(gè)在寫入時(shí),且沒有適當(dāng)?shù)耐?,就?huì)發(fā)生數(shù)據(jù)競(jìng)爭(zhēng)。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var count int
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            count++
        }()
    }

    wg.Wait()
    fmt.Println("Count:", count)
}

使用go run -race運(yùn)行此代碼會(huì)顯示競(jìng)爭(zhēng)條件。通過使用互斥鎖來修正它:

var mu sync.Mutex
mu.Lock()
count++
mu.Unlock()

優(yōu)點(diǎn):防止數(shù)據(jù)競(jìng)爭(zhēng)確保一致性和穩(wěn)定性,這對(duì)具有共享數(shù)據(jù)的并發(fā)進(jìn)程的應(yīng)用程序至關(guān)重要。

結(jié)論

利用 goroutine、channel 及同步原語(yǔ),Go 能夠高效發(fā)揮多核并行能力。遵循最佳實(shí)踐、妥善管理資源和錯(cuò)誤,可構(gòu)建高性能且易維護(hù)的并發(fā)應(yīng)用。

責(zé)任編輯:趙寧寧 來源: 令飛編程
相關(guān)推薦

2023-11-27 15:49:55

軟件開發(fā)系統(tǒng)設(shè)計(jì)

2013-06-26 09:42:52

Web開發(fā)URL編碼URL

2019-11-23 23:38:51

開發(fā)者微服務(wù)安全

2023-11-17 14:18:48

開發(fā)編程

2019-11-20 12:09:01

JavaScriptGitHub工具

2022-04-27 09:48:56

JS前端開發(fā)

2018-10-16 11:03:19

API開發(fā)者AR

2023-08-11 18:11:49

2025-03-05 09:21:08

2021-03-09 10:26:24

Python開發(fā)工具

2025-01-07 10:01:10

2019-05-24 09:04:31

C++編程語(yǔ)言開發(fā)

2020-01-14 08:28:50

Linux命令程序

2014-03-07 14:20:30

2017-04-05 12:04:17

python函數(shù)

2012-02-28 10:52:13

2018-03-07 12:57:53

2024-09-02 14:30:43

2020-06-03 18:10:46

GitHub代碼庫(kù)前端

2018-05-03 08:45:58

Linux命令
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)