日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

你是否想知道如何應(yīng)對高并發(fā)?Go語言為你提供了答案!

來源: 責(zé)編: 時間:2024-01-02 09:31:33 212觀看
導(dǎo)讀并發(fā)編程是當(dāng)前軟件領(lǐng)域中不可忽視的一個關(guān)鍵概念。隨著CPU等硬件的不斷發(fā)展,我們都渴望讓我們的程序運行速度更快、更快。而Go語言在語言層面天生支持并發(fā),充分利用現(xiàn)代CPU的多核優(yōu)勢,這也是Go語言能夠廣泛流行的一個重

并發(fā)編程是當(dāng)前軟件領(lǐng)域中不可忽視的一個關(guān)鍵概念。隨著CPU等硬件的不斷發(fā)展,我們都渴望讓我們的程序運行速度更快、更快。而Go語言在語言層面天生支持并發(fā),充分利用現(xiàn)代CPU的多核優(yōu)勢,這也是Go語言能夠廣泛流行的一個重要原因。Y7o28資訊網(wǎng)——每日最新資訊28at.com

在Java中,要支持高并發(fā)有幾種方案可供選擇。首先,我們可以通過開啟多部署節(jié)點集群來增加高并發(fā)處理能力,通過增加機器硬件來實現(xiàn)。其次,我們可以在單節(jié)點上開啟多線程來處理請求。然而,即使在單節(jié)點內(nèi)創(chuàng)建線程也是非常耗費資源的。因此,通常情況下我們會使用線程池來管理線程的創(chuàng)建和銷毀。然而,有一個公式你可能會很熟悉,即核心線程數(shù)等于CPU核數(shù)的一半加一。這意味著我們并不是線程創(chuàng)建得越多,對于我們的Java程序就越好。Y7o28資訊網(wǎng)——每日最新資訊28at.com

在我們明確了問題的痛點之后,我們可以進一步探究一下Go語言是如何解決這些問題,并且將高并發(fā)作為Go語言的一項特色功能。Y7o28資訊網(wǎng)——每日最新資訊28at.com

goroutine

我們在Java中開啟線程的方式是直接創(chuàng)建一個Thread對象。然而,在Go語言中,如果我們想要實現(xiàn)異步處理,我們可以使用"go"關(guān)鍵字來開啟一個goroutine協(xié)程。協(xié)程的最大優(yōu)勢在于其輕量級,可以輕松創(chuàng)建上百萬個協(xié)程而不會導(dǎo)致系統(tǒng)資源的耗盡,而線程和進程通常最多也不能超過1萬個。舉個例子:Y7o28資訊網(wǎng)——每日最新資訊28at.com

go f()  // 創(chuàng)建一個新的 goroutine 運行函數(shù)f

在Go語言中,我們可以非常簡單地使用關(guān)鍵字"go"來開啟一個協(xié)程,從而實現(xiàn)異步處理函數(shù)f。只需在函數(shù)f的調(diào)用前面加上"go"關(guān)鍵字,就能使得該函數(shù)在一個獨立的協(xié)程中異步執(zhí)行。Y7o28資訊網(wǎng)——每日最新資訊28at.com

不僅可以使用"go"關(guān)鍵字來開啟一個協(xié)程異步執(zhí)行具名函數(shù),還可以使用"go"關(guān)鍵字來開啟一個協(xié)程異步執(zhí)行匿名函數(shù)。Y7o28資訊網(wǎng)——每日最新資訊28at.com

go func(){  // ...}()

今天我們的重點不在這里,而是要討論為什么Go語言適合處理高并發(fā)的情況。我們都知道,操作系統(tǒng)的CPU最小調(diào)度單位是線程,然而Go語言卻使用了協(xié)程的概念。那么問題來了,Go語言是如何將這些協(xié)程交給CPU來處理的呢?如果無法將它們交給CPU處理,那么就算再創(chuàng)建多少協(xié)程也無法運行代碼。在這里,我們就需要了解一下Go語言的調(diào)度器,也就是GPM調(diào)度模型。Y7o28資訊網(wǎng)——每日最新資訊28at.com

GPM調(diào)度模型

可以借鑒一下以下圖例,總的來說,我們可以像線程池一樣,無論創(chuàng)建了多少協(xié)程,都需要將它們放入隊列中。然后,剩下的任務(wù)就交給調(diào)度器來處理。Y7o28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Y7o28資訊網(wǎng)——每日最新資訊28at.com

其中:Y7o28資訊網(wǎng)——每日最新資訊28at.com

  • G:使用關(guān)鍵字"go"加上一個函數(shù)調(diào)用可以創(chuàng)建一個goroutine(簡稱G)。每次調(diào)用"go f()"都會創(chuàng)建一個新的G,其中包含要執(zhí)行的函數(shù)f以及相關(guān)的上下文信息。
  • 全局隊列(Global Queue)是用來存放等待運行的 G(Goroutine)的地方。
  • P 是指 goroutine 執(zhí)行所需的物理資源,每個 P 最多可以承載 GOMAXPROCS 個 goroutine 的執(zhí)行。
  • P 的本地隊列是類似于全局隊列的,它存放了等待運行的G,并且數(shù)量限制在256個以內(nèi)。每當(dāng)新建一個G時,優(yōu)先將其加入到P的本地隊列中,如果本地隊列已滿,則會批量移動部分G到全局隊列中。
  • 為了使線程能夠執(zhí)行任務(wù),需要通過獲取調(diào)度器(P)來獲取任務(wù)(G)。線程首先嘗試從調(diào)度器的本地隊列獲取任務(wù),如果本地隊列為空,則線程會嘗試從全局隊列或其他調(diào)度器的本地隊列獲取任務(wù)。一旦線程獲取到任務(wù),就會執(zhí)行任務(wù),并在任務(wù)執(zhí)行完畢后再次從調(diào)度器獲取下一個任務(wù),持續(xù)重復(fù)這個過程。

Goroutine 調(diào)度器和操作系統(tǒng)調(diào)度器通過 M 結(jié)合起來,形成了調(diào)度的基本單位。在這個結(jié)合中,每個 M 代表一個內(nèi)核線程,而操作系統(tǒng)調(diào)度器則負責(zé)將這些內(nèi)核線程分配到 CPU 的核心上進行執(zhí)行。Y7o28資訊網(wǎng)——每日最新資訊28at.com

channel

單純地將函數(shù)并發(fā)執(zhí)行是沒有意義的,因為函數(shù)與函數(shù)之間需要進行數(shù)據(jù)交換,才能真正體現(xiàn)并發(fā)執(zhí)行函數(shù)的意義。Y7o28資訊網(wǎng)——每日最新資訊28at.com

雖然可以利用共享內(nèi)存進行數(shù)據(jù)交換,但是在不同的 goroutine 中使用共享內(nèi)存容易導(dǎo)致競態(tài)問題的出現(xiàn)。為了確保數(shù)據(jù)交換的正確性,許多并發(fā)模型都需要通過使用互斥量對內(nèi)存進行加鎖來解決這個問題。然而,這種做法往往會帶來性能問題,因為加鎖操作會引入額外的開銷。Y7o28資訊網(wǎng)——每日最新資訊28at.com

Go語言采用的并發(fā)模型是CSP(Communicating Sequential Processes),這個模型強調(diào)了通過通信共享內(nèi)存的方式來實現(xiàn)并發(fā),而不是通過共享內(nèi)存來實現(xiàn)通信。這種設(shè)計理念使得Go語言在處理并發(fā)任務(wù)時更加高效和安全。Y7o28資訊網(wǎng)——每日最新資訊28at.com

如果說 goroutine 是Go程序中實現(xiàn)并發(fā)執(zhí)行的主體,那么channel就是連接這些goroutine之間的紐帶。channel是一種能夠使得一個goroutine向另一個goroutine發(fā)送特定值的通信機制。Y7o28資訊網(wǎng)——每日最新資訊28at.com

Mutex(互斥鎖)在實現(xiàn)上也是使用了重量級鎖。與Java的互斥鎖相比,Go語言的Mutex有以下幾點區(qū)別:Y7o28資訊網(wǎng)——每日最新資訊28at.com

內(nèi)存開銷:Go語言的Mutex相對較輕量,使用較少的內(nèi)存。這是因為Go語言的Mutex只包含一個字段,用于表示鎖的狀態(tài),而Java的互斥鎖通常包含更多的字段和數(shù)據(jù)結(jié)構(gòu)。Y7o28資訊網(wǎng)——每日最新資訊28at.com

鎖的語法:在Go語言中,可以使用mutex.Lock()和mutex.Unlock()方法來手動控制鎖的獲取和釋放,這樣可以更靈活地控制鎖的粒度。而在Java中,使用synchronized關(guān)鍵字來實現(xiàn)互斥鎖,鎖的粒度相對固定,只能對整個方法或代碼塊進行加鎖。Y7o28資訊網(wǎng)——每日最新資訊28at.com

鎖的性能:由于Go語言的Mutex較為輕量,并且采用了更高效的實現(xiàn)方式,比如以下幾個方面:Y7o28資訊網(wǎng)——每日最新資訊28at.com

  • 自旋鎖:在低并發(fā)的情況下,Go語言的Mutex會采用自旋鎖的方式。自旋鎖是一種忙等待的鎖,當(dāng)一個Goroutine嘗試獲取鎖時,如果鎖已經(jīng)被其他Goroutine持有,則該Goroutine會一直循環(huán)檢查鎖的狀態(tài),直到成功獲取鎖。這種方式避免了線程切換的開銷,提高了性能。
  • 優(yōu)化的調(diào)度策略:Go語言的調(diào)度器在處理Goroutine的調(diào)度時會進行優(yōu)化,盡量將鎖的持有者與等待者調(diào)度到同一個處理器(P)上執(zhí)行,減少線程之間的上下文切換和鎖競爭的開銷。
  • 等待隊列:當(dāng)一個Goroutine無法獲取到Mutex鎖時,它會進入等待隊列,等待鎖的釋放。Go語言的Mutex的等待隊列是基于鏈表實現(xiàn)的,相比Java的互斥鎖使用的等待隊列,具有更低的內(nèi)存開銷和更高的效率。

總結(jié)

并發(fā)編程是當(dāng)前軟件領(lǐng)域中一個重要的概念。Go語言通過goroutine和channel的特性,天生支持高并發(fā)處理,充分利用現(xiàn)代CPU的多核優(yōu)勢。與Java相比,Go語言的協(xié)程更加輕量級,可以輕松創(chuàng)建上百萬個協(xié)程。Go語言的調(diào)度器采用GPM調(diào)度模型,通過將協(xié)程放入隊列中,由調(diào)度器分配給CPU處理。此外,Go語言采用CSP模型,通過channel實現(xiàn)協(xié)程之間的通信,避免了共享內(nèi)存帶來的競態(tài)問題。相比之下,Go語言的Mutex鎖更輕量、靈活,并且具有更高的性能。總的來說,Go語言適合處理高并發(fā)的情況,成為了當(dāng)前軟件開發(fā)領(lǐng)域的熱門語言之一。Y7o28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-55254-0.html你是否想知道如何應(yīng)對高并發(fā)?Go語言為你提供了答案!

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 我們一起聊聊K8s定時備份MySQL并發(fā)送到指定郵箱

下一篇: 你是否想知道如何應(yīng)對高并發(fā)?Go語言為你提供了答案!

標(biāo)簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 闽清县| 延庆县| 容城县| 镇坪县| 固原市| 临武县| 安国市| 洱源县| 鄂温| 沅陵县| 阳江市| 五寨县| 兴国县| 龙门县| 那坡县| 天全县| 施秉县| 皋兰县| 红河县| 资兴市| 连江县| 汪清县| 腾冲县| 德格县| 吴江市| 若尔盖县| 蒙自县| 灵石县| 临夏市| 十堰市| 册亨县| 乌鲁木齐市| 大同县| 丹棱县| 九寨沟县| 静宁县| 抚松县| 金乡县| 浮山县| 义乌市| 余干县|