成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go 學習:并發編程

開發 前端
聊到并發,就會有一系列的其他概念相繼而來,比如:并行、進程、線程、異步等。

Go 語言在創建之初,CPU 多核發展正猛,Go 語言的創始人果斷將面向多核、原生支持并發作為了 Go 語言的設計目標之一,所以在 Go 語言中使用并發有得天獨厚的優勢。

那么,什么是并發呢?

聊到并發,就會有一系列的其他概念相繼而來,比如:并行、進程、線程、異步等。

我們經常使用 C# 的 Winform 程序寫一些工具,編譯后為一個 exe 文件,文件執行后就會作為一個進程在 Windows 中執行,在之前的單核 CPU 時代,在某個時刻只能執行一個進程對應的程序代碼,兩個進程不存在并行執行的可能,多個處理器或多核處理器是并行執行的必要條件。

如果對程序進行改造,對執行的任務進行分解,每個分解出來的小的模塊由一個單獨的線程進行處理,多個線程共享這個進程所擁有的資源,線程作為執行單元可被獨立調度到處理器上運行。也許還是執行在單 CPU 中,但是在并發執行的。

Go 語言的創始人 Rob Pike 曾說過:并行關乎執行,并發關乎結構。

舉一個生活中的例子:

現在每天都在做的排隊做核酸,有三個步驟:

1、排隊。

2、掃二維碼。

3、捅喉嚨。

圖片


  • 需要做核酸的人分多個隊伍進行排隊,多個隊伍在并行進行處理。
  • 每一個隊伍中只有一個檢測人員,先進行掃碼,然后去捅喉嚨,兩個步驟完成后,再進行下一個。

圖片


  • 掃碼和捅喉嚨都有單獨的人員進行處理,這就像將程序拆分成多個線程進行處理一樣。
  • 并發在單 CPU 也能發生,就像上圖中只有一個隊伍的情況,但多核或多 CPU 能發揮更大的作用。

由此可見,要發揮并發的作用,離不開線程和多核,線程創建的成本雖然已經比進程小了很多,但依然不適合大規模地創建線程,因為除了每個線程占用的資源外,操作系統調度線程的成本也不小。

因此,Go 語言創造了 goroutine ,也叫協程,這是一個由 Go 運行時負責調度的輕量級線程。和常規的線程相比,有這些好處:

  • 資源占用小, goroutine 的 Stack 的初始化的大小為 2k ,而像 C# 、Java 語言中線程的 Stack 都是兆級別的,所以 goroutine 的創建會更加快;
  • goroutine 是由 Go 運行時調度,而不是操作系統,切換速度會更快。

在 Go 中怎樣使用 goroutine 呢?非常的簡單,使用關鍵字 go 就可以了,默認情況下,主程序在單獨的一個 goroutine 中,如果某個函數或匿名函數使用了 go 關鍵字,那么就會創建一個單獨的 goroutine 。

package main

import (
"fmt"
"time"
)

func testGouroutine(name string) {
fmt.Println("goroutine:", name)
}
func main() {
fmt.Println("這是主程序")
go testGouroutine("1")
go testGouroutine("2")
go testGouroutine("3")
go testGouroutine("4")
time.Sleep(time.Second)
}

如果在使用 go 關鍵字的函數中使用了主程序中的資源,就會出現競爭的情況,看下面的這個例子:

package main

import (
"fmt"
"time"
)

func test() {
counter := 0
for i := 0; i < 5000; i++ {
go func() {
counter++
}()
}
time.Sleep(time.Second)
fmt.Println("counter:", counter)
}

func main() {
test()
}

每次運行,counter 的值都會不一樣,因為每次不同的協程對公共資源 counter 的搶奪情況不一樣,要解決這個問題就要用到鎖:

package main

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

func test() {
var mut sync.Mutex

counter := 0
for i := 0; i < 5000; i++ {
go func() {
defer mut.Unlock()
mut.Lock()
counter++
}()
}
time.Sleep(time.Second)

fmt.Println("counter:", counter)
}

func main() {
test()
}

值得注意的是,使用 go 關鍵字執行的函數即便是有返回值,也會被忽略,如果需要在 goroutine 之間進行通信,需要使用通道。

通道使用 make 進行構建,關鍵字為 chan 。看下面的例子:

package main

import (
"fmt"
"strconv"
"time"
)

func main() {
//使用 make 創建一個字符型的通道,通道使用關鍵字 chan
msg := make(chan string)
//在異步匿名函數中模擬同步數據,完成一個給通道發送一個消息
go func() {
for i := 1; i <= 10; i++ {
if i == 10 {
msg <- "success"
} else {
msg <- "總共需要同步 10 個模塊,已經處理 " + strconv.Itoa(i) + "個"
}
//每循環依次,演示 1 秒,模擬耗時
time.Sleep(time.Second)
}
}()

//主線程中進行進度顯示
for m := range msg {
if m == "success" {
fmt.Println("同步完成")
break
} else {
fmt.Println(m)
}
}
}

在匿名函數中每隔一秒就給主 gorourine 發送一個消息,主 gorourine 把這個消息打印出來。

最后總結下:

1、并行關乎執行,并發關乎結構。

2、Go 語言的并發是基于輕量級的 goroutine ,相比普通的線程,goroutine 有很多的好處。

3、在不同的 goroutine 之間進行通信需要用到通道,通道使用 make 創建,關鍵字為 chan 。

責任編輯:姜華 來源: 不止dotNET
相關推薦

2022-04-24 15:29:17

微服務go

2017-11-10 11:27:48

Go并行算法

2023-02-10 09:40:36

Go語言并發

2023-11-27 18:07:05

Go并發編程

2024-07-08 00:01:00

GPM模型調度器

2025-06-17 09:32:15

2023-10-28 15:37:39

Go編程語言

2024-09-06 10:48:13

2020-01-14 11:17:33

Go并發Linux

2024-05-06 07:53:09

Go并發編程

2021-03-24 06:06:13

Go并發編程Singlefligh

2024-06-19 10:08:34

GoChannel工具

2024-03-05 18:24:52

I/O聚合優化存儲

2024-04-11 07:40:55

Go并發編程

2025-03-24 00:25:00

Go語言并發編程

2021-09-30 09:21:28

Go語言并發編程

2024-10-14 08:51:52

協程Go語言

2024-06-17 08:40:16

2024-07-30 12:24:23

2021-02-24 19:03:00

開源技術 編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩一区二区在线播放 | 免费在线精品视频 | 免费国产成人av | 国产1区2区在线观看 | 一区二区中文 | 亚洲国产精品91 | 亚洲国产欧美日韩 | 色网在线观看 | 成人在线精品视频 | 亚洲成年影院 | 国产在线网址 | 欧美区日韩区 | 三级视频在线观看电影 | 日本在线一二 | 色偷偷噜噜噜亚洲男人 | 国产成人免费视频网站视频社区 | 亚洲高清视频一区二区 | 国产精品麻 | 一级片av | 日韩欧美精品在线播放 | 少妇一级淫片免费播放 | 久久精品一级 | 日韩在线观看中文字幕 | 亚洲a在线观看 | a久久 | 久久性色 | 亚欧洲精品在线视频免费观看 | 中文字幕视频在线看 | 国产精品久久久久久久久久免费看 | 欧美视频网 | 国产免费一区 | 99re在线播放 | av免费成人 | 亚洲精品高清视频在线观看 | 自拍偷拍第一页 | 国产精品一区在线观看 | 玖玖免费 | 成人在线视频网址 | 欧美精品一区二区三区蜜桃视频 | 国产1区2区在线观看 | 91精品国产91久久久久久最新 |