第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

多生產者/多消費者并發(fā)

多生產者/多消費者并發(fā)

Go
SMILET 2021-09-27 17:23:08
我可能遺漏了一些東西,或者不了解 Go 如何處理并發(fā)(或者我對并發(fā)本身的了解),我設計了一些代碼來理解多個生產者/消費者。這是代碼:package mainimport (    "fmt"    "time"    // "math/rand"    "sync")var seq uint64 = 0var generatorChan chan uint64var requestChan chan uint64func makeTimestamp() int64 {    return time.Now().UnixNano() / int64(time.Millisecond)}func generateStuff(genId int) {    var crap uint64    for {        crap = <-requestChan        // <- requestChan        seq = seq+1        fmt.Println("Gen ", genId, " - From : ", crap, " @", makeTimestamp())        generatorChan <- uint64(seq)    }}func concurrentPrint(id int, work *sync.WaitGroup) {    defer work.Done()    for i := 0; i < 5; i++ {        requestChan<-uint64(id)        fmt.Println("Conc", id, ": ", <-generatorChan)    }}func main() {    generatorChan = make(chan uint64)    requestChan = make(chan uint64)    var wg sync.WaitGroup    for i := 0; i < 20; i++ {        go generateStuff(i)    }    maximumWorker := 200    wg.Add(maximumWorker)    for i := 0; i < maximumWorker; i++ {        go concurrentPrint(i, &wg)    }    wg.Wait()}運行時,它會打?。ㄖ饕前错樞颍?1 到 1000 的所有數(shù)字(200 個消費者每個獲得一個數(shù)字 5 次)。我原以為某些消費者會打印完全相同的數(shù)字,但即使有 20 個 goroutine 為generateStuff服務,通過增加全局變量來生成數(shù)字,但requestChan似乎正在像一個障礙一樣工作,以防止這種情況發(fā)生。一般來說,我對 Go 或 Concurrency 有什么誤解?我原以為會出現(xiàn)兩個類似generateStuff類型的 go 例程會被一起喚醒并同時增加 seq 的情況,從而導致兩個消費者兩次打印相同的數(shù)字。在 playgolang 上編輯代碼:http ://play.golang.org/p/eRzNXjdxtZ
查看完整描述

2 回答

?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

您有多個可以同時運行的工作人員,并且所有工作人員都可以同時嘗試和發(fā)出請求。由于requestChan是無緩沖的,它們都阻塞等待讀取器同步并接受他們的請求。

您有多個生成器,它們將通過 與請求者同步requestChan,生成結果,然后阻塞無緩沖,generatorChan直到工作人員讀取結果。請注意,它可能是不同的工人。

沒有額外的同步,所以其他一切都是不確定的。

  • 一個生成器可以處理所有請求。

  • 生成器可以獲取請求并seq 在任何其他生成器有機會運行之前通過遞增。只有一個處理器,這甚至是可能的。

  • 所有的生成器都可以獲取請求,并且最終都想要seq在完全相同的時間遞增,從而導致各種問題。

  • 工作人員可以從他們碰巧發(fā)送到或來自完全不同的生成器的同一生成器中獲得響應。

通常,如果不添加同步來強制執(zhí)行這些行為中的一種,則無法確保其中任何一種行為確實發(fā)生。

請注意,對于數(shù)據(jù)競爭,這本身就是另一個非確定性事件。有可能獲得任意值、程序崩潰等。假設在競爭條件下該值可能只是被一個或一些這樣的相對無害的結果關閉是不安全的。

對于試驗,您能做的最好的事情就是加速GOMAXPROCS。通過環(huán)境變量(例如類似env GOMAXPROCS=16 go run foo.goenv GOMAXPROCS=16 ./foo之后go build)或runtime.GOMAXPROCS(16)從您的程序調用。默認值為 1,這意味著可能會隱藏數(shù)據(jù)競爭或其他“奇怪”行為。

您還可以通過在不同的點添加調用runtime.Goschedtime.Sleep在不同的點上來影響一些事情。

如果您使用競爭檢測器(例如使用go run -race foo.googo build -race),您還可以看到數(shù)據(jù)競爭。程序不僅應該在退出時顯示“Found 1 data race(s)”,而且還應該在首次檢測到競爭時轉儲大量帶有堆棧跟蹤的詳細信息。

這是用于實驗的代碼的“清理”版本:

package main


import (

    "log"

    "sync"

    "sync/atomic"

)


var seq uint64 = 0

var generatorChan = make(chan uint64)

var requestChan = make(chan uint64)


func generator(genID int) {

    for reqID := range requestChan {

        // If you want to see a data race:

        //seq = seq + 1

        // Else:

        s := atomic.AddUint64(&seq, 1)

        log.Printf("Gen: %2d, from %3d", genID, reqID)

        generatorChan <- s

    }

}


func worker(id int, work *sync.WaitGroup) {

    defer work.Done()


    for i := 0; i < 5; i++ {

        requestChan <- uint64(id)

        log.Printf("\t\t\tWorker: %3d got %4d", id, <-generatorChan)

    }

}


func main() {

    log.SetFlags(log.Lmicroseconds)

    const (

        numGen    = 20

        numWorker = 200

    )

    var wg sync.WaitGroup

    for i := 0; i < numGen; i++ {

        go generator(i)

    }

    wg.Add(numWorker)

    for i := 0; i < numWorker; i++ {

        go worker(i, &wg)

    }

    wg.Wait()

    close(requestChan)

}

Playground(但請注意,playground 上的時間戳沒有用,調用runtime.MAXPROCS可能沒有任何作用)。進一步注意,playground 會緩存結果,因此重新運行完全相同的程序將始終顯示相同的輸出,您需要進行一些小的更改或僅在您自己的機器上運行它。


很多小的變化,比如關閉生成器,使用logvsfmt因為前者可以保證并發(fā)性,消除數(shù)據(jù)競爭,使輸出看起來更好等。


查看完整回答
反對 回復 2021-09-27
?
拉莫斯之舞

TA貢獻1820條經驗 獲得超10個贊

渠道類型

通道為并發(fā)執(zhí)行函數(shù)提供了一種機制,通過發(fā)送和接收指定元素類型的值來進行通信。未初始化通道的值為 nil。

可以使用內置函數(shù) make 創(chuàng)建一個新的初始化通道值,該函數(shù)將通道類型和可選容量作為參數(shù):

make(chan?int,?100)

容量(以元素數(shù)為單位)設置通道中緩沖區(qū)的大小。如果容量為零或不存在,則通道沒有緩沖,只有當發(fā)送方和接收方都準備好時,通信才能成功。否則,如果緩沖區(qū)未滿(發(fā)送)或非空(接收),則通道被緩沖并且通信成功而不會阻塞。一個 nil 通道永遠不會準備好進行通信。

您正在使用無緩沖通道來限制通道通信。

例如,

generatorChan?=?make(chan?uint64)
requestChan?=?make(chan?uint64)


查看完整回答
反對 回復 2021-09-27
  • 2 回答
  • 0 關注
  • 258 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號