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

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

多生產(chǎn)者/多消費(fèi)者并發(fā)

多生產(chǎn)者/多消費(fèi)者并發(fā)

Go
SMILET 2021-09-27 17:23:08
我可能遺漏了一些東西,或者不了解 Go 如何處理并發(fā)(或者我對(duì)并發(fā)本身的了解),我設(shè)計(jì)了一些代碼來(lái)理解多個(gè)生產(chǎn)者/消費(fèi)者。這是代碼: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()}運(yùn)行時(shí),它會(huì)打?。ㄖ饕前错樞颍?1 到 1000 的所有數(shù)字(200 個(gè)消費(fèi)者每個(gè)獲得一個(gè)數(shù)字 5 次)。我原以為某些消費(fèi)者會(huì)打印完全相同的數(shù)字,但即使有 20 個(gè) goroutine 為generateStuff服務(wù),通過(guò)增加全局變量來(lái)生成數(shù)字,但requestChan似乎正在像一個(gè)障礙一樣工作,以防止這種情況發(fā)生。一般來(lái)說(shuō),我對(duì) Go 或 Concurrency 有什么誤解?我原以為會(huì)出現(xiàn)兩個(gè)類(lèi)似generateStuff類(lèi)型的 go 例程會(huì)被一起喚醒并同時(shí)增加 seq 的情況,從而導(dǎo)致兩個(gè)消費(fèi)者兩次打印相同的數(shù)字。在 playgolang 上編輯代碼:http ://play.golang.org/p/eRzNXjdxtZ
查看完整描述

2 回答

?
收到一只叮咚

TA貢獻(xiàn)1821條經(jīng)驗(yàn) 獲得超5個(gè)贊

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

您有多個(gè)生成器,它們將通過(guò) 與請(qǐng)求者同步requestChan,生成結(jié)果,然后阻塞無(wú)緩沖,generatorChan直到工作人員讀取結(jié)果。請(qǐng)注意,它可能是不同的工人。

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

  • 一個(gè)生成器可以處理所有請(qǐng)求。

  • 生成器可以獲取請(qǐng)求并seq 在任何其他生成器有機(jī)會(huì)運(yùn)行之前通過(guò)遞增。只有一個(gè)處理器,這甚至是可能的。

  • 所有的生成器都可以獲取請(qǐng)求,并且最終都想要seq在完全相同的時(shí)間遞增,從而導(dǎo)致各種問(wèn)題。

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

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

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

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

您還可以通過(guò)在不同的點(diǎn)添加調(diào)用runtime.Goschedtime.Sleep在不同的點(diǎn)上來(lái)影響一些事情。

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

這是用于實(shí)驗(yàn)的代碼的“清理”版本:

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(但請(qǐng)注意,playground 上的時(shí)間戳沒(méi)有用,調(diào)用runtime.MAXPROCS可能沒(méi)有任何作用)。進(jìn)一步注意,playground 會(huì)緩存結(jié)果,因此重新運(yùn)行完全相同的程序?qū)⑹冀K顯示相同的輸出,您需要進(jìn)行一些小的更改或僅在您自己的機(jī)器上運(yùn)行它。


很多小的變化,比如關(guān)閉生成器,使用logvsfmt因?yàn)榍罢呖梢员WC并發(fā)性,消除數(shù)據(jù)競(jìng)爭(zhēng),使輸出看起來(lái)更好等。


查看完整回答
反對(duì) 回復(fù) 2021-09-27
?
拉莫斯之舞

TA貢獻(xiàn)1820條經(jīng)驗(yàn) 獲得超10個(gè)贊

渠道類(lèi)型

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

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

make(chan?int,?100)

容量(以元素?cái)?shù)為單位)設(shè)置通道中緩沖區(qū)的大小。如果容量為零或不存在,則通道沒(méi)有緩沖,只有當(dāng)發(fā)送方和接收方都準(zhǔn)備好時(shí),通信才能成功。否則,如果緩沖區(qū)未滿(發(fā)送)或非空(接收),則通道被緩沖并且通信成功而不會(huì)阻塞。一個(gè) nil 通道永遠(yuǎn)不會(huì)準(zhǔn)備好進(jìn)行通信。

您正在使用無(wú)緩沖通道來(lái)限制通道通信。

例如,

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


查看完整回答
反對(duì) 回復(fù) 2021-09-27
  • 2 回答
  • 0 關(guān)注
  • 248 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)