婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > go獲取協程(goroutine)號的實例

go獲取協程(goroutine)號的實例

熱門標簽:谷歌美發店地圖標注 地圖區域圖標注后導出 官渡電銷外呼管理系統怎么收費 貴州電話智能外呼系統 赤峰電銷 江蘇呼叫中心外呼系統有效果嗎 利用地圖標注位置 400開頭電話怎樣申請 杭州人工智能電銷機器人費用

我就廢話不多說了,大家還是直接看代碼吧~

func GetGID() uint64 {
    b := make([]byte, 64)
    b = b[:runtime.Stack(b, false)]
    b = bytes.TrimPrefix(b, []byte("goroutine "))
    b = b[:bytes.IndexByte(b, ' ')]
    n, _ := strconv.ParseUint(string(b), 10, 64)
    return n
}

補充:Go語言并發協程Goroutine和通道channel

Go語言并發協程Goroutine

1.1 Go語言競爭狀態

有并發,就有資源競爭,如果兩個或者多個 goroutine 在沒有相互同步的情況下,訪問某個共享的資源,比如同時對該資源進行讀寫時,就會處于相互競爭的狀態,這就是并發中的資源競爭。

并發本身并不復雜,但是因為有了資源競爭的問題,就使得我們開發出好的并發程序變得復雜起來,因為會引起很多莫名其妙的問題。

以下代碼就會出現競爭狀態:

import (
  "fmt"
  "runtime"
  "sync"
)
var (
  count int32
  wg  sync.WaitGroup
)
func main() {
  wg.Add(2)
  go incCount()
  go incCount()
  wg.Wait()
  fmt.Println(count)
}
func incCount() {
  defer wg.Done()
  for i := 0; i  2; i++ {
    value := count
    runtime.Gosched()
    value++
    count = value
  }
}

count 變量沒有任何同步保護,所以兩個 goroutine 都會對其進行讀寫,會導致對已經計算好的結果被覆蓋,以至于產生錯誤結果。

代碼中的 runtime.Gosched() 是讓當前 goroutine 暫停的意思,退回執行隊列runq,讓其他等待的 goroutine 運行,目的是為了使資源競爭的結果更明顯,下次運行暫停的goroutine時從斷點處開始。

分析程序運行過程:

g1 讀取到 count 的值為 0;

然后 g1 暫停了,切換到 g2 運行,g2 讀取到 count 的值也為 0;

g2 暫停,切換到 g1暫停的位置繼續運行,g1 對 count+1,count 的值變為 1;

g1 暫停,切換到 g2,g2 剛剛已經獲取到值 0,對其 +1,最后賦值給 count,其結果還是 1;

可以看出 g1 對 count+1 的結果被 g2 給覆蓋了,兩個 goroutine 都 +1 而結果還是 1。

通過上面的分析可以看出,之所以出現上面的問題,是因為兩個 goroutine 相互覆蓋結果。

所以我們對于同一個資源的讀寫必須是原子化的,也就是說,同一時間只能允許有一個 goroutine 對共享資源進行讀寫操作。 此例子的共享資源就是count

通過go build -race生成一個可以執行文件,然后再運行這個可執行文件,就可以檢測資源競爭信息,看到打印出的檢測信息。如下

==================
WARNING: DATA RACE
Read at 0x000000619cbc by goroutine 8:
 main.incCount()
   D:/code/src/main.go:25 +0x80// goroutine 8 在代碼 25 行讀取共享資源value := count
Previous write at 0x000000619cbc by goroutine 7:
 main.incCount()
   D:/code/src/main.go:28 +0x9f// goroutine 7 在代碼 28行修改共享資源count=value
Goroutine 8 (running) created at:
 main.main()
   D:/code/src/main.go:17 +0x7e
Goroutine 7 (finished) created at:
 main.main()
   D:/code/src/main.go:16 +0x66//兩個 goroutine 都是從 main 函數的 16、17 行通過 go 關鍵字啟動的。
==================
4
Found 1 data race(s)

1.2 鎖住共享資源

Go語言提供了傳統的同步 goroutine 的機制,就是對共享資源加鎖。atomic 和 sync 包里的一些函數就可以對共享的資源進行加鎖操作。

1.2.1 原子函數

原子函數能夠以很底層的加鎖機制來同步訪問整型變量和指針

import (
  "fmt"
  "runtime"
  "sync"
  "sync/atomic"
)
var (
  counter int64
  wg   sync.WaitGroup
)
func main() {
  wg.Add(2)
  go incCounter(1)
  go incCounter(2)
  wg.Wait() //等待goroutine結束
  fmt.Println(counter)
}
func incCounter(id int) {
  defer wg.Done()
  for count := 0; count  2; count++ {
    atomic.AddInt64(counter, 1) //安全的對counter加1
    runtime.Gosched()
  }
}

上述代碼中使用了 atmoic 包的 AddInt64 函數,這個函數會同步整型值的加法,方法是強制同一時刻只能有一個 gorountie 運行并完成這個加法操作。

另外兩個有用的原子函數是 LoadInt64 和 StoreInt64。這兩個函數提供了一種安全地讀和寫一個整型值的方式。下面的代碼就使用了 LoadInt64 和 StoreInt64 函數來創建一個同步標志,這個標志可以向程序里多個 goroutine 通知某個特殊狀態。

import (
  "fmt"
  "sync"
  "sync/atomic"
  "time"
)
var (
  shutdown int64
  wg    sync.WaitGroup
)
func main() {
  wg.Add(2)
  go doWork("A")
  go doWork("B")
  time.Sleep(1 * time.Second)
  fmt.Println("Shutdown Now")
  atomic.StoreInt64(shutdown, 1)
  wg.Wait()
}
func doWork(name string) {
  defer wg.Done()
  for {
    fmt.Printf("Doing %s Work\n", name)
    time.Sleep(250 * time.Millisecond)
    if atomic.LoadInt64(shutdown) == 1 {
      fmt.Printf("Shutting %s Down\n", name)
      break
    }
  }
}
--output--
Doing A Work
Doing B Work
Doing B Work
Doing A Work
Doing A Work
Doing B Work
Doing B Work
Doing A Work//前8行順序每次運行時都不一樣
Shutdown Now
Shutting A Down
Shutting B Down//A和B都shut down后,由wg.Done()把計數器置0

上面代碼中 main 函數使用 StoreInt64 函數來安全地修改 shutdown 變量的值。如果哪個 doWork goroutine 試圖在 main 函數調用 StoreInt64 的同時調用 LoadInt64 函數,那么原子函數會將這些調用互相同步,保證這些操作都是安全的,不會進入競爭狀態。

1.2.2 鎖

見上篇文章,上面的例子為保持同步,取消競爭,可照以下操作:

func incCounter(id int) {
  defer wg.Done()
  for count := 0; count  2; count++ {
    //同一時刻只允許一個goroutine進入這個臨界區
    mutex.Lock()
    {
      value := counter
      runtime.Gosched()//退出當前goroutine,調度器會再次分配這個 goroutine 繼續運行。
      value++
      counter = value
    }
    mutex.Unlock() //釋放鎖,允許其他正在等待的goroutine進入臨界區
  }
}

1.3 通道chan

統統將通道兩端的goroutine理解為生產者-消費者模式。

通道的數據接收一共有以下 4 種寫法。

阻塞接收數據

阻塞模式接收數據時,將接收變量作為-操作符的左值,格式如下:

data := -ch

執行該語句時將會阻塞,直到接收到數據并賦值給 data 變量。

2) 非阻塞接收數據

使用非阻塞方式從通道接收數據時,語句不會發生阻塞,格式如下:

data, ok := -ch

data:表示接收到的數據。未接收到數據時,data 為通道類型的零值。

ok:表示是否接收到數據。

非阻塞的通道接收方法可能造成高的 CPU 占用,因此使用非常少。如果需要實現接收超時檢測,可以配合 select 和計時器 channel 進行

3) 循環接收數據

import (
  "fmt"
  "time"
)
func main() {
  // 構建一個通道,這里有沒有緩沖都可,因為是收了就發,無需阻塞等待
  ch := make(chan int)
  // 開啟一個并發匿名函數
  go func() {
    // 從3循環到0
    for i := 3; i >= 0; i-- {
      // 發送3到0之間的數值
      ch - i
      // 每次發送完時等待
      time.Sleep(time.Second)
    }
  }()
  // 遍歷接收通道數據
  for data := range ch {
    // 打印通道數據
    fmt.Println(data)
    // 當遇到數據0時, 退出接收循環
    if data == 0 {
        break
    }
  }
}
--output--

1.3.1 單向通道

ch := make(chan int)
// 聲明一個只能寫入數據的通道類型, 并賦值為ch
var chSendOnly chan- int = ch
或
ch := make(chan- int)
//聲明一個只能讀取數據的通道類型, 并賦值為ch
var chRecvOnly -chan int = ch
或
ch := make(-chan int)

1.3.2 優雅的關閉通道

1.3.3 無緩沖的通道

如果兩個 goroutine 沒有同時準備好,通道會導致先執行發送或接收操作的 goroutine 阻塞等待。(阻塞指的是由于某種原因數據沒有到達,當前協程(線程)持續處于等待狀態,直到條件滿足才解除阻塞)這種對通道進行發送和接收的交互行為本身就是同步的。其中任意一個操作都無法離開另一個操作單獨存在。

在網球比賽中,兩位選手會把球在兩個人之間來回傳遞。選手總是處在以下兩種狀態之一,要么在等待接球,要么將球打向對方。可以使用兩個 goroutine 來模擬網球比賽,并使用無緩沖的通道來模擬球的來回

// 這個示例程序展示如何用無緩沖的通道來模擬
// 2 個goroutine 間的網球比賽
package main
import (
  "fmt"
  "math/rand"
  "sync"
  "time"
)
// wg 用來等待程序結束
var wg sync.WaitGroup
func init() {
  rand.Seed(time.Now().UnixNano())
}
// main 是所有Go 程序的入口
func main() {
  // 創建一個無緩沖的通道
  court := make(chan int)
  // 計數加 2,表示要等待兩個goroutine
  wg.Add(2)
  // 啟動兩個選手
  go player("Nadal", court)
  go player("Djokovic", court)
  // 發球
  court - 1
  // 等待游戲結束
  wg.Wait()
}
// player 模擬一個選手在打網球
func player(name string, court chan int) {
  // 在函數退出時調用Done 來通知main 函數工作已經完成
  defer wg.Done()
  for {
    // 等待球被擊打過來
    ball, ok := -court
    if !ok {
      // 如果通道被關閉,我們就贏了
      fmt.Printf("Player %s Won\n", name)
      return
    }
    // 選隨機數,然后用這個數來判斷我們是否丟球
    n := rand.Intn(100)
    if n%13 == 0 {
      fmt.Printf("Player %s Missed\n", name)
      // 關閉通道,表示我們輸了
      close(court)
      return
    }
    // 顯示擊球數,并將擊球數加1
    fmt.Printf("Player %s Hit %d\n", name, ball)
    ball++
    // 將球打向對手,為啥這里是把ball發送到另一個go協程?
    //因為court無緩沖,此時另一個go協程正好在等待接收court內的值,所以此時轉向另一個go協程代碼
    court - ball
  }
}

1.3.4 有緩沖的通道

有緩沖的通道是一種在被接收前能存儲一個或者多個值的通道。這種類型的通道并不強制要求 goroutine 之間必須同時完成發送和接收,發送和接受的阻塞條件為只有在通道中沒有要接收的值時,接收動作才會阻塞。只有在通道沒有可用緩沖區容納被發送的值時,發送動作才會阻塞。

有緩沖的通道和無緩沖的通道之間的一個很大的不同:無緩沖的通道保證進行發送和接收的 goroutine 會在同一時間進行數據交換;有緩沖的通道沒有這種保證。

為什么要給通道限制緩沖區大小?

通道(channel)是在兩個 goroutine 間通信的橋梁。使用 goroutine 的代碼必然有一方提供數據,一方消費數據。當提供數據一方的數據供給速度大于消費方的數據處理速度時,如果通道不限制長度,那么內存將不斷膨脹直到應用崩潰。因此,限制通道的長度有利于約束數據提供方的供給速度,供給數據量必須在消費方處理量+通道長度的范圍內,才能正常地處理數據。

1.3.5 channel超時機制

select 機制不是專門為超時而設計的,卻能很方便的解決超時問題,因為 select 的特點是只要其中有一個 case 已經完成,程序就會繼續往下執行,而不會考慮其他 case 的情況。

基本語句為:

每個 case 語句里必須是一個 IO 操作,

select {
  case -chan1:
  // 如果chan1成功讀到數據,則進行該case處理語句
  case chan2 - 1:
  // 如果成功向chan2寫入數據,則進行該case處理語句
  default:
  // 如果上面都沒有成功,則進入default處理流程
}

例子,注意之所以輸出5個num,是因為select里的time.After在這里的意思是ch通道無值可以接收的時候的3s后才print超時,即最多ch通道最多阻塞等待3s

func main() {
  ch := make(chan int)
  quit := make(chan bool)
  //新開一個協程
  go func() {
    for {
      select {
      case num := -ch:
        fmt.Println("num = ", num)
      case -time.After(3 * time.Second):
        fmt.Println("超時")
        quit - true
      }
    }
  }() //別忘了()
  for i := 0; i  5; i++ {
    ch - i
    time.Sleep(time.Second)//主協程進入休眠狀態,等待上面的go協程運行并進入阻塞等待狀態,就這樣來回運行,并通過chan通信
  }
  -quit
  fmt.Println("程序結束")
}
--output--
num = 0
num = 1
num = 2
num = 3
num = 4
超時
程序結束

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • Go語言并發模型的2種編程方案
  • golang gin 框架 異步同步 goroutine 并發操作
  • Golang 探索對Goroutine的控制方法(詳解)
  • 關于Golang中for-loop與goroutine的問題詳解
  • go語言執行等待直到后臺goroutine執行完成實例分析
  • Go語言輕量級線程Goroutine用法實例
  • 分析Go語言中CSP并發模型與Goroutine的基本使用

標簽:武漢 河池 保定 宜春 松原 泰安 鷹潭 黔西

巨人網絡通訊聲明:本文標題《go獲取協程(goroutine)號的實例》,本文關鍵詞  獲取,協程,goroutine,號的,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《go獲取協程(goroutine)號的實例》相關的同類信息!
  • 本頁收集關于go獲取協程(goroutine)號的實例的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲一区自拍偷拍| 国产精品卡一卡二卡三| 国产欧美日本一区视频| 一区二区三区日本| 国产精品一二三区| 欧美一区二区三区喷汁尤物| 亚洲乱码日产精品bd| 国模套图日韩精品一区二区 | 日韩欧美一区二区三区在线| 中文字幕一区三区| 国产在线精品视频| 欧美高清一级片在线| 亚洲视频图片小说| 成人av高清在线| 精品国产免费一区二区三区香蕉| 亚洲二区视频在线| 欧美自拍丝袜亚洲| 一区二区三区高清在线| a在线播放不卡| 国产精品乱人伦| 国产成人综合亚洲91猫咪| 日韩午夜在线播放| 视频在线观看国产精品| 欧美日韩成人综合| 亚洲成av人片在线观看| 欧美亚洲一区三区| 亚洲国产精品久久人人爱| 在线观看日韩毛片| 午夜久久久影院| 欧美久久免费观看| 秋霞影院一区二区| 欧美大片在线观看一区| 另类小说图片综合网| 日韩欧美成人午夜| 国产精品一级在线| 欧美激情综合五月色丁香| 粉嫩欧美一区二区三区高清影视| 国产欧美一区二区在线| 成人激情图片网| 午夜不卡av在线| 欧美日韩一区三区四区| 亚洲mv大片欧洲mv大片精品| 制服丝袜亚洲网站| 国产在线一区观看| 成人免费在线播放视频| 在线观看国产91| 蜜臀久久久99精品久久久久久| 欧美成人乱码一区二区三区| 精品一区二区综合| 国产精品久久福利| 欧美三区在线视频| 精品一区二区三区的国产在线播放| 国产亚洲一区二区三区四区| 91蜜桃网址入口| 亚洲va天堂va国产va久| 欧美tk—视频vk| 99国产欧美另类久久久精品| 亚洲123区在线观看| 欧美变态tickling挠脚心| 成人毛片在线观看| 天天综合网 天天综合色| 久久综合色鬼综合色| 一本久久综合亚洲鲁鲁五月天 | 精品久久久三级丝袜| 国产91对白在线观看九色| 一区二区三区蜜桃| 欧美xingq一区二区| 91麻豆高清视频| 久久99国内精品| 亚洲精品久久7777| 久久久久久久国产精品影院| 欧美午夜在线一二页| 国产福利一区在线| 婷婷久久综合九色国产成人| 国产精品久久久久久福利一牛影视 | 欧美一区二区视频网站| 高潮精品一区videoshd| 日韩精品一级二级| 综合中文字幕亚洲| 精品少妇一区二区三区视频免付费| 91欧美激情一区二区三区成人| 久久精品国产精品亚洲精品| 亚洲精品福利视频网站| 久久免费偷拍视频| 91精品一区二区三区在线观看| 91亚洲男人天堂| 国产999精品久久久久久| 免费不卡在线观看| 亚洲成精国产精品女| 亚洲欧美日韩国产综合| 国产精品网站在线播放| 精品久久久网站| 日韩一区二区免费在线电影| 欧美伊人久久大香线蕉综合69 | 青青草97国产精品免费观看| 亚洲已满18点击进入久久| 亚洲成av人片www| 亚洲人精品午夜| 国产精品沙发午睡系列990531| 精品国产一区二区三区忘忧草 | 精久久久久久久久久久| 亚洲成人动漫一区| 亚洲国产日韩综合久久精品| 亚洲人成网站精品片在线观看| 国产精品乱人伦中文| 国产精品国产精品国产专区不片| 久久久久88色偷偷免费| 久久伊人蜜桃av一区二区| 久久嫩草精品久久久精品一| 久久久综合精品| 久久精品一区蜜桃臀影院| 久久久久久久久97黄色工厂| 久久精品男人的天堂| 国产欧美视频一区二区| 中文字幕一区二区三区在线播放 | 国产三级精品视频| 中文字幕欧美激情一区| 国产精品天美传媒沈樵| 国产精品乱人伦一区二区| 亚洲日本在线a| 一区二区三区鲁丝不卡| 五月天丁香久久| 欧美无人高清视频在线观看| 亚洲电影一区二区三区| 91美女精品福利| 美女久久久精品| 国产主播一区二区| 国产一区免费电影| 不卡一二三区首页| 91在线无精精品入口| 日本道色综合久久| 欧美精品一二三区| 国产午夜精品一区二区| 亚洲免费观看高清完整版在线观看 | 国产精品久久久久久一区二区三区| 国产精品萝li| 亚洲一区电影777| 蜜桃视频免费观看一区| 国v精品久久久网| 在线观看一区二区视频| 欧美成人精品高清在线播放| 中文天堂在线一区| 亚洲一级不卡视频| 日本中文一区二区三区| 国产成人在线视频网址| 色欧美乱欧美15图片| 一本色道a无线码一区v| 一本到三区不卡视频| 欧美三级日韩三级| 日韩美一区二区三区| 18成人在线观看| 日本不卡高清视频| 不卡视频一二三| 日韩欧美国产一区二区三区| 国产精品久久久久久久久搜平片| 视频一区二区三区在线| jvid福利写真一区二区三区| 欧美高清在线视频| 三级不卡在线观看| 91蝌蚪porny| 国产片一区二区三区| 视频精品一区二区| 色综合久久综合中文综合网| 精品国产99国产精品| 亚洲免费伊人电影| 国产白丝精品91爽爽久久| 69久久夜色精品国产69蝌蚪网| 国产精品欧美一级免费| 久久99蜜桃精品| 精品视频999| 有码一区二区三区| 91在线看国产| 国产日韩欧美亚洲| 免费成人美女在线观看.| 欧美视频在线播放| 日韩美女视频一区二区 | 色综合久久天天综合网| 久久久久久久久99精品| 久久精品国产亚洲a| 欧美日韩国产天堂| 一区二区三区精品久久久| 国产精品 日产精品 欧美精品| 国产精品久久看| 亚洲一区二区视频| 久久不见久久见免费视频1| 欧美日韩亚洲国产综合| 亚洲女同一区二区| 色天使色偷偷av一区二区| 国产精品久久福利| 成人丝袜高跟foot| 国产精品伦理一区二区| jlzzjlzz国产精品久久| 国产精品久久久久久一区二区三区| 高清国产一区二区三区| 国产精品福利在线播放| 不卡大黄网站免费看| 亚洲色欲色欲www在线观看| www.亚洲色图| 亚洲精品精品亚洲| 欧美乱妇一区二区三区不卡视频|