<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 臨界資源的安全問題(引入同步異步處理)

          共 3951字,需瀏覽 8分鐘

           ·

          2022-06-10 05:12

          作者:LiberHome

          來源:SegmentFault  思否社區(qū) 


          臨界資源定義



          并發(fā)環(huán)境中多個進程、線程、協(xié)程共享的資源


          臨界資源的特點



          可能會因為并發(fā)操作導(dǎo)致數(shù)據(jù)出現(xiàn)不一致性,舉個栗子,下面代碼中的a及時臨界資源


          package main

          import (
              "fmt"
              "time"
          )

          func main() {
              //臨界資源
              a := 1
              go func() {
                  a = 2
                  fmt.Println("in this goroutine: a is : ", a)
              }()
              //在主goroutine中
              a = 3
              time.Sleep(1)
              fmt.Println("in the main goroutine: a is : ", a)
          }


          經(jīng)典的售票問題,好多個窗口同時售票的門票的數(shù)量就是一個典型的臨界資源安全問題,下面用4個協(xié)程模擬一下售票過程:


          package main

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

          var ticket = 10 //the amount of the total ticket is 100
          func main() {
              //這里啟動4個goroutine模擬4個售票口 同時售票
              go saleTickets("ticket window1")
              go saleTickets("ticket window2")
              go saleTickets("ticket window3")
              go saleTickets("ticket window4")
              //這里為了保證 主協(xié)程 最后執(zhí)行完 先用sleep (當(dāng)然,也可以用同步等待組、chanel實現(xiàn))
              time.Sleep(10 * time.Second)
          }

          func saleTickets(name string) {
              rand.Seed(time.Now().UnixNano())
              for {
                  if ticket > 0 {
                      time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
                      fmt.Println(name, "saled: ", ticket)
                      ticket--
                  } else {
                      fmt.Println(name, "sorry tickets are sold out")
                      break
                  }
              }
          }


          運行結(jié)果如下:


          ticket window3 saled:  10
          ticket window1 saled:  9
          ticket window4 saled:  8
          ticket window2 saled:  7
          ticket window3 saled:  6
          ticket window2 saled:  5
          ticket window1 saled:  4
          ticket window1 saled:  3
          ticket window4 saled:  2
          ticket window2 saled:  1
          ticket window2 sorry tickets are sold out
          ticket window4 saled:  0
          ticket window4 sorry tickets are sold out
          ticket window3 saled:  -1
          ticket window3 sorry tickets are sold out
          ticket window1 saled:  -2
          ticket window1 sorry tickets are sold out


          這里居然賣出了-2張票,這明顯除了問題,問題出在哪里呢?


          • 我們假設(shè)現(xiàn)在只剩下最后1張票了,現(xiàn)在程序在主協(xié)程里面

          • 窗口4的協(xié)程拿到cpu資源,讀取了剩余ticket總數(shù)為1,然后sleep,釋放cpu資源

          • 窗口3的協(xié)程拿到cpu資源,發(fā)現(xiàn)剩余ticket總數(shù)為1(因為窗口4的協(xié)程進入sleep了,并沒有在窗口3拿到cpu資源之前對ticket進行修改),然后sleep,釋放cpu資源。

          • 窗口4醒了,ticket = 1 - 1 = 0

          • 窗口3醒了,ticket = 0 - 1 = -1


          針對這種問題,可以通過上鎖,在某一時間段只允許一個goroutine來訪問這個共享數(shù)據(jù),訪問完畢,解鎖之后,其他goroutine才能訪問的方式解決。

          不過有意思的是,go并不鼓勵這樣以共享的方式去通信,而是以通信的方式去共享【也就是不鼓勵用sync包上鎖,鼓勵使用chanel】


          資源參考:https://www.bilibili.com/video/BV1jJ411c7s3



          點擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 30
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕the same porn | 丰满人妻一区二区三区性色 | 黄色大尺度视频 | 国产女人叫高视频 | 尹人网午夜视频 |