最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

GO語(yǔ)言臨界資源安全問(wèn)題的深入理解

 更新時(shí)間:2021年12月09日 10:24:08   作者:Davie老師  
臨界資源安全問(wèn)題也就是以往我們常聽(tīng)到的線(xiàn)程安全問(wèn)題,本文詳細(xì)的介紹了GO語(yǔ)言臨界資源安全問(wèn)題的深入理解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、臨界資源

臨界資源: 指并發(fā)環(huán)境中多個(gè)進(jìn)程/線(xiàn)程/協(xié)程共享的資源。

但是在并發(fā)編程中對(duì)臨界資源的處理不當(dāng), 往往會(huì)導(dǎo)致數(shù)據(jù)不一致的問(wèn)題。

示例代碼:

package main
?
import (
    "fmt"
    "time"
)
?
func main()  {
    a := 1
    go func() {
        a = 2
        fmt.Println("子goroutine。。",a)
    }()
    a = 3
    time.Sleep(1)
    fmt.Println("main goroutine。。",a)
}

我們通過(guò)終端命令來(lái)執(zhí)行:

能夠發(fā)現(xiàn)一處被多個(gè)goroutine共享的數(shù)據(jù)。

二、臨界資源安全問(wèn)題

并發(fā)本身并不復(fù)雜,但是因?yàn)橛辛速Y源競(jìng)爭(zhēng)的問(wèn)題,就使得我們開(kāi)發(fā)出好的并發(fā)程序變得復(fù)雜起來(lái),因?yàn)闀?huì)引起很多莫名其妙的問(wèn)題。

如果多個(gè)goroutine在訪(fǎng)問(wèn)同一個(gè)數(shù)據(jù)資源的時(shí)候,其中一個(gè)線(xiàn)程修改了數(shù)據(jù),那么這個(gè)數(shù)值就被修改了,對(duì)于其他的goroutine來(lái)講,這個(gè)數(shù)值可能是不對(duì)的。

舉個(gè)例子,我們通過(guò)并發(fā)來(lái)實(shí)現(xiàn)火車(chē)站售票這個(gè)程序。一共有100張票,4個(gè)售票口同時(shí)出售。

我們先來(lái)看一下示例代碼:

package main
?
import (
    "fmt"
    "math/rand"
    "time"
)
?
//全局變量
var ticket = 10 // 100張票
?
func main() {
    /*
    4個(gè)goroutine,模擬4個(gè)售票口,4個(gè)子程序操作同一個(gè)共享數(shù)據(jù)。
     */
    go saleTickets("售票口1") // g1,100
    go saleTickets("售票口2") // g2,100
    go saleTickets("售票口3") //g3,100
    go saleTickets("售票口4") //g4,100
?
    time.Sleep(5*time.Second)
}
?
func saleTickets(name string) {
    rand.Seed(time.Now().UnixNano())
    //for i:=1;i<=100;i++{
    //  fmt.Println(name,"售出:",i)
    //}
    for { //ticket=1
        if ticket > 0 { //g1,g3,g2,g4
            //睡眠
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
            // g1 ,g3, g2,g4
            fmt.Println(name, "售出:", ticket)  // 1 , 0, -1 , -2
            ticket--   //0 , -1 ,-2 , -3
        } else {
            fmt.Println(name,"售罄,沒(méi)有票了。。")
            break
        }
    }
}
?

我們?yōu)榱烁玫挠^察臨界資源問(wèn)題,每個(gè)goroutine先睡眠一個(gè)隨機(jī)數(shù),然后再售票,我們發(fā)現(xiàn)程序的運(yùn)行結(jié)果,還可以賣(mài)出編號(hào)為負(fù)數(shù)的票。

分析:

我們的賣(mài)票邏輯是先判斷票數(shù)的編號(hào)是否為負(fù)數(shù),如果大于0,然后我們就進(jìn)行賣(mài)票,只不過(guò)在賣(mài)票錢(qián)先睡眠,然后再賣(mài),假如說(shuō)此時(shí)已經(jīng)賣(mài)票到只剩最后1張了,某一個(gè)goroutine持有了CPU的時(shí)間片,那么它再片段是否有票的時(shí)候,條件是成立的,所以它可以賣(mài)票編號(hào)為1的最后一張票。但是因?yàn)樗谫u(mài)之前,先睡眠了,那么其他的goroutine就會(huì)持有CPU的時(shí)間片,而此時(shí)這張票還沒(méi)有被賣(mài)出,那么第二個(gè)goroutine再判斷是否有票的時(shí)候,條件也是成立的,那么它可以賣(mài)出這張票,然而它也進(jìn)入了睡眠。。其他的第三個(gè)第四個(gè)goroutine都是這樣的邏輯,當(dāng)某個(gè)goroutine醒來(lái)的時(shí)候,不會(huì)再判斷是否有票,而是直接售出,這樣就賣(mài)出最后一張票了,然而其他的goroutine醒來(lái)的時(shí)候,就會(huì)陸續(xù)賣(mài)出了第0張,-1張,-2張。

這就是臨界資源的不安全問(wèn)題。某一個(gè)goroutine在訪(fǎng)問(wèn)某個(gè)數(shù)據(jù)資源的時(shí)候,按照數(shù)值,已經(jīng)判斷好了條件,然后又被其他的goroutine搶占了資源,并修改了數(shù)值,等這個(gè)goroutine再繼續(xù)訪(fǎng)問(wèn)這個(gè)數(shù)據(jù)的時(shí)候,數(shù)值已經(jīng)不對(duì)了。

三、臨界資源安全問(wèn)題的解決

要想解決臨界資源安全的問(wèn)題,很多編程語(yǔ)言的解決方案都是同步。通過(guò)上鎖的方式,某一時(shí)間段,只能允許一個(gè)goroutine來(lái)訪(fǎng)問(wèn)這個(gè)共享數(shù)據(jù),當(dāng)前goroutine訪(fǎng)問(wèn)完畢,解鎖后,其他的goroutine才能來(lái)訪(fǎng)問(wèn)。

我們可以借助于sync包下的鎖操作。

示例代碼:

package main
?
import (
    "fmt"
    "math/rand"
    "time"
    "sync"
)
?
//全局變量
var ticket = 10 // 100張票
?
var wg sync.WaitGroup
var matex sync.Mutex // 創(chuàng)建鎖頭
?
func main() {
    /*
    4個(gè)goroutine,模擬4個(gè)售票口,4個(gè)子程序操作同一個(gè)共享數(shù)據(jù)。
     */
    wg.Add(4)
    go saleTickets("售票口1") // g1,100
    go saleTickets("售票口2") // g2,100
    go saleTickets("售票口3") //g3,100
    go saleTickets("售票口4") //g4,100
    wg.Wait()              // main要等待。。。
?
    //time.Sleep(5*time.Second)
}
?
func saleTickets(name string) {
    rand.Seed(time.Now().UnixNano())
    defer wg.Done()
    //for i:=1;i<=100;i++{
    //  fmt.Println(name,"售出:",i)
    //}
    for { //ticket=1
        matex.Lock()
        if ticket > 0 { //g1,g3,g2,g4
            //睡眠
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
            // g1 ,g3, g2,g4
            fmt.Println(name, "售出:", ticket) // 1 , 0, -1 , -2
            ticket--                         //0 , -1 ,-2 , -3
        } else {
            matex.Unlock() //解鎖
            fmt.Println(name, "售罄,沒(méi)有票了。。")
            break
        }
        matex.Unlock() //解鎖
    }
}
?

運(yùn)行結(jié)果:

四、寫(xiě)在最后

在Go的并發(fā)編程中有一句很經(jīng)典的話(huà):不要以共享內(nèi)存的方式去通信,而要以通信的方式去共享內(nèi)存。

在Go語(yǔ)言中并不鼓勵(lì)用鎖保護(hù)共享狀態(tài)的方式在不同的Goroutine中分享信息(以共享內(nèi)存的方式去通信)。而是鼓勵(lì)通過(guò)channel將共享狀態(tài)或共享狀態(tài)的變化在各個(gè)Goroutine之間傳遞(以通信的方式去共享內(nèi)存),這樣同樣能像用鎖一樣保證在同一的時(shí)間只有一個(gè)Goroutine訪(fǎng)問(wèn)共享狀態(tài)。

當(dāng)然,在主流的編程語(yǔ)言中為了保證多線(xiàn)程之間共享數(shù)據(jù)安全性和一致性,都會(huì)提供一套基本的同步工具集,如鎖,條件變量,原子操作等等。Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)也毫不意外的提供了這些同步機(jī)制,使用方式也和其他語(yǔ)言也差不多。

到此這篇關(guān)于GO語(yǔ)言臨界資源安全問(wèn)題的深入理解的文章就介紹到這了,更多相關(guān)GO語(yǔ)言臨界資源安全 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在goland中讀取tpl文件的圖文操作

    在goland中讀取tpl文件的圖文操作

    這篇文章主要介紹了在goland中讀取tpl文件的圖文操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go語(yǔ)言單線(xiàn)程運(yùn)行也會(huì)有的并發(fā)問(wèn)題解析

    Go語(yǔ)言單線(xiàn)程運(yùn)行也會(huì)有的并發(fā)問(wèn)題解析

    這篇文章主要為大家介紹了Go語(yǔ)言單線(xiàn)程運(yùn)行的并發(fā)問(wèn)題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go語(yǔ)言使用組合的思想實(shí)現(xiàn)繼承

    Go語(yǔ)言使用組合的思想實(shí)現(xiàn)繼承

    這篇文章主要為大家詳細(xì)介紹了在 Go 里面如何使用組合的思想實(shí)現(xiàn)“繼承”,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以了解一下
    2022-12-12
  • 詳解Golang如何優(yōu)雅的終止一個(gè)服務(wù)

    詳解Golang如何優(yōu)雅的終止一個(gè)服務(wù)

    后端服務(wù)通常會(huì)需要?jiǎng)?chuàng)建子協(xié)程來(lái)進(jìn)行相應(yīng)的作業(yè),但進(jìn)程接受到終止信號(hào)或正常結(jié)束時(shí),并沒(méi)有判斷或等待子協(xié)程執(zhí)行結(jié)束,下面這篇文章主要給大家介紹了關(guān)于Golang如何優(yōu)雅的終止一個(gè)服務(wù)的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • golang對(duì)自定義類(lèi)型進(jìn)行排序的解決方法

    golang對(duì)自定義類(lèi)型進(jìn)行排序的解決方法

    學(xué)習(xí)一門(mén)編程語(yǔ)言,要掌握原子數(shù)據(jù)類(lèi)型,還需要掌握自定義數(shù)據(jù)類(lèi)型。下面這篇文章主要給大家介紹了關(guān)于golang如何對(duì)自定義類(lèi)型進(jìn)行排序的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。
    2017-12-12
  • 使用Go語(yǔ)言封裝實(shí)現(xiàn)郵件發(fā)送功能

    使用Go語(yǔ)言封裝實(shí)現(xiàn)郵件發(fā)送功能

    在現(xiàn)代 Web 開(kāi)發(fā)中,郵件發(fā)送功能是一個(gè)常見(jiàn)的需求,本文將介紹如何在 Go 語(yǔ)言中封裝一個(gè)通用的郵件發(fā)送包,支持驗(yàn)證碼發(fā)送和通用郵件發(fā)送,需要的可以參考下
    2025-03-03
  • 使用Go語(yǔ)言自制簡(jiǎn)單易用的Web框架

    使用Go語(yǔ)言自制簡(jiǎn)單易用的Web框架

    這篇文章主要為大家詳細(xì)介紹了如何使用Go語(yǔ)言實(shí)現(xiàn)自制簡(jiǎn)單易用的Web框架,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • 詳解Go語(yǔ)言實(shí)現(xiàn)線(xiàn)性查找算法和二分查找算法

    詳解Go語(yǔ)言實(shí)現(xiàn)線(xiàn)性查找算法和二分查找算法

    線(xiàn)性查找又稱(chēng)順序查找,它是查找算法中最簡(jiǎn)單的一種。二分查找,也稱(chēng)折半查找,相比于線(xiàn)性查找,它是一種效率較高的算法。本文將用Go語(yǔ)言實(shí)現(xiàn)這兩個(gè)查找算法,需要的可以了解一下
    2022-12-12
  • go語(yǔ)言題解LeetCode1299將每個(gè)元素替換為右側(cè)最大元素

    go語(yǔ)言題解LeetCode1299將每個(gè)元素替換為右側(cè)最大元素

    這篇文章主要為大家介紹了go語(yǔ)言L(fǎng)eetCode刷題1299將每個(gè)元素替換為右側(cè)最大元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 簡(jiǎn)單講解Go程序中使用MySQL的方法

    簡(jiǎn)單講解Go程序中使用MySQL的方法

    這篇文章主要介紹了Go程序中使用MySQL的方法,需要使用第三方包來(lái)進(jìn)行連接,需要的朋友可以參考下
    2015-10-10

最新評(píng)論

达拉特旗| 桐乡市| 平潭县| 镇坪县| 肥城市| 黄骅市| 昭觉县| 新龙县| 鄢陵县| 枝江市| 阜城县| 新沂市| 吐鲁番市| 阜南县| 安康市| 湖南省| 合肥市| 襄樊市| 阜南县| 民勤县| 乌审旗| 泰宁县| 佛教| 漳平市| 米易县| 高唐县| 衡南县| 彭阳县| 广饶县| 大同市| 广南县| 儋州市| 盘山县| 绥宁县| 班戈县| 浦东新区| 桃园县| 乌兰浩特市| 万载县| 疏勒县| 苗栗县|