Kiitos, että tilasit

Johdanto

kun aloin ensimmäistä kertaa työskennellä Gon kanavien kanssa, erehdyin ajattelemaan kanavia tietorakenteena. Näin kanavat jonona, joka tarjosi automaattisen synkronoidun pääsyn goroutinesin välille. Tämä rakenteellinen ymmärrys sai minut kirjoittamaan paljon huonoa ja monimutkaista samanaikaista koodia.

opin ajan myötä, että on parasta unohtaa kanavien rakenne ja keskittyä siihen, miten ne käyttäytyvät. Joten nyt kun se tulee kanavia, ajattelen yksi asia: signalointi. Kanava mahdollistaa yhden goroutine signaalin toisen goroutine noin tietyn tapahtuman. Signalointi on kaiken sen ytimessä, mitä kanavilla pitäisi tehdä. Kun ajattelet kanavia signalointimekanismina, voit kirjoittaa parempaa koodia hyvin määritellyllä ja tarkemmalla käytöksellä.

ymmärtääksemme, miten signalointi toimii, meidän täytyy ymmärtää sen kolme ominaisuutta:

  • toimitusvarmuus
  • tila
  • tietojen kanssa tai ilman

nämä kolme ominaisuutta luovat yhdessä suunnittelufilosofian signaloinnin ympärille. Kun olen keskustellut näistä attribuuteista, annan useita koodiesimerkkejä, jotka osoittavat signalointia näillä attribuuteilla.

Toimitustakuu

Toimitustakuu perustuu yhteen kysymykseen: ”Tarvitsenko takuun siitä, että tietyn gorutiinin lähettämä signaali on vastaanotettu?”

toisin sanoen, ottaen huomioon tämän esimerkin listauksessa 1:

listaus 1

01 go func() {02 p := <-ch // Receive03 }()0405 ch <- "paper" // Send

tarvitseeko lähettävä goroutine takeet siitä, että kanaalin yli linjalla 05 lähetetty paper on saanut linjan 02 goroutine ennen siirtymistään?

tähän kysymykseen annetun vastauksen perusteella tiedät, kumpaa kanavaa käyttää: Puskuroimatonta vai puskuroitua. Jokainen kanava tarjoaa erilaisen käyttäytymisen noin takeet toimitus.

Kuva 1: Toimitustakuu

Toimitustakuu

vakuudet ovat tärkeitä, ja jos et usko niin, minulla on tonni asioita, joita haluan myydä sinulle. Totta kai yritän vitsailla, mutta eikö hermostuta, kun elämässä ei ole takuita? Ottaa vahva käsitys siitä, onko tarvitset takuu on ratkaisevan tärkeää kirjoitettaessa samanaikaisia ohjelmistoja. Kun jatkamme,opit päättämään.

tila

kanavan käyttäytymiseen vaikuttaa suoraan sen nykytila. Kanavan tila voi olla nolla, avoin tai suljettu.

alla oleva luettelo 2 osoittaa, miten kukin näistä kolmesta valtiosta julistetaan tai asetetaan kanava.

listaus 2

// ** nil channel// A channel is in a nil state when it is declared to its zero valuevar ch chan string// A channel can be placed in a nil state by explicitly setting it to nil.ch = nil// ** open channel// A channel is in a open state when it's made using the built-in function make.ch := make(chan string) // ** closed channel// A channel is in a closed state when it's closed using the built-in function close.close(ch)

valtio määrää, miten send and receive-operaatiot käyttäytyvät.

signaalit lähetetään ja vastaanotetaan kanavan kautta. Älä sano Lue/kirjoita, koska kanavat eivät suorita I/O.

kuva 2 : tila

tila

kun kanava on nollatilassa, kaikki lähetykset tai vastaanotot kanavalla estyvät. Kun kanava on avoimessa tilassa, signaaleja voidaan lähettää ja vastaanottaa. Kun kanava asetetaan suljettuun tilaan, signaaleja ei voida enää lähettää, mutta signaalien vastaanottaminen on edelleen mahdollista.

nämä tilat tarjoavat erilaisia käyttäytymismalleja, joita tarvitset kohtaamiisi erilaisiin tilanteisiin. Kun yhdistät tilan ja toimitustakuun, voit alkaa analysoida suunnitteluvalintojesi aiheuttamia kustannuksia / hyötyjä. Monissa tapauksissa voit myös nopeasti havaita vikoja pelkästään koodia lukemalla, koska ymmärrät, miten kanava tulee käyttäytymään.

kanssa ja ilman tietoa

viimeinen huomioitava signalointiominaisuus on, tarvitseeko signaloida datalla vai ilman.

signaloit datalla suorittamalla lähetyksen kanavalla.

listaus 3

01 ch <- "paper"

kun signaloit datalla, se on yleensä koska:

  • goroutinea pyydetään aloittamaan uusi tehtävä.
  • goroutine raportoi tuloksen.

signaloit ilman dataa sulkemalla kanavan.

listaus 4

01 close(ch)

kun signaali ilman dataa, se on yleensä koska:

  • goroutinea käsketään lopettamaan se, mitä he tekevät.
  • goroutine raportoi takaisin ne tehdään ilman tulosta.
  • goroutine ilmoittaa saaneensa käsittelyn päätökseen ja sulkeneensa.

näistä säännöistä on poikkeuksia, mutta nämä ovat tärkeimmät käyttötapaukset ja ne, joihin keskitymme tässä viestissä. Pidän poikkeuksia näistä säännöistä alkukoodina.

yksi signaloinnin etu ilman dataa on, että yksi goroutiini voi signaloida monta goroutiinia kerralla. Signalointi tietojen kanssa on aina 1-1 vaihto goroutines.

signalointi datalla

kun signaloit datalla, voit valita kolme kanavaasetusvaihtoehtoa riippuen takuutyypistä.

kuva 3 : Signalointi datalla

kolme kanavavaihtoehtoa ovat puskuroimaton, puskuroitu >1 tai puskuroitu =1.

  • takuu

    • puskuroimaton kanava antaa takuun siitä, että lähetetty signaali on vastaanotettu.
      • , koska signaalin vastaanottaminen tapahtuu ennen signaalin lähettämistä loppuun.
  • ei takeita

    • puskuroitu kanava, jonka koko on >1, ei anna takeita siitä, että lähetettävää signaalia on vastaanotettu.
      • koska signaalin lähettäminen tapahtuu ennen signaalin vastaanottamista.
  • viivästynyt takuu

    • puskuroitu kanava, jonka Koko =1 antaa viivästyneen takuun. Se voi taata, että edellinen lähetetty signaali on vastaanotettu.
      • koska ensimmäisen signaalin vastaanottaminen tapahtuu ennen toisen signaalin lähettämistä.

puskurin koko ei saa koskaan olla satunnaisluku, se on aina laskettava jollekin hyvin määritellylle rajoitukselle. Tietojenkäsittelyssä ei ole äärettömyyttä, kaikella on oltava jokin hyvin määritelty rajoitus, oli se sitten aika tai avaruus.

signalointi ilman tietoa

signalointi ilman tietoa on pääasiassa varattu peruutukseen. Sen avulla yksi goroutine signaalin toisen goroutine peruuttaa mitä he tekevät ja siirtyä eteenpäin. Peruutus voidaan toteuttaa sekä Puskuroimattomilla että Puskuroiduilla kanavilla, mutta puskuroidun kanavan käyttäminen silloin, kun Tietoja ei lähetetä, on koodinhajua.

Kuva 4 : Signalointi ilman dataa

sisäänrakennettua funktiota close käytetään signaaliin ilman dataa. Kuten edellä Valtion osassa, voit silti vastaanottaa signaaleja kanavalla, joka on suljettu. Itse asiassa kaikki vastaanotot suljetulla kanavalla eivät estä ja vastaanottotoiminta palaa aina.

useimmissa tapauksissa haluat käyttää standardikirjastoa context pakettia signaloinnin toteuttamiseen ilman dataa. context-paketti käyttää alla olevaa Puskuroimatonta kanavaa signalointiin ja sisäänrakennettua toimintoa close signalointiin ilman dataa.

jos päätät käyttää peruutukseen omaa kanavaa kontekstipaketin sijaan, kanavasi tulee olla tyyppiä chan struct{}. Se on nollatila, idiomaattinen tapa osoittaa kanava, jota käytetään vain merkinantoon.

skenaariot

kun nämä ominaisuudet ovat käytössä, paras tapa ymmärtää niiden toimintaa käytännössä on käydä läpi sarja koodiskenaarioita. Tykkään ajatella goroutineja ihmisinä, kun luen ja kirjoitan kanavapohjaista koodia. Tämä visualisointi todella auttaa, ja aion käyttää sitä apuna alla.

signaali Datatakuulla-Puskuroimattomat kanavat

kun täytyy tietää, että lähetetty signaali on vastaanotettu, tulee kaksi skenaariota. Nämä ovat odottaa tehtävän ja odottaa tuloksia.

Skenaario 1-odota tehtävää

mieti esimiehenä olemista ja uuden työntekijän palkkaamista. Tässä skenaariossa, haluat uuden työntekijän suorittamaan tehtävän, mutta ne täytyy odottaa, kunnes olet valmis. Tämä johtuu siitä, että sinun täytyy antaa heille pala paperia ennen kuin ne alkavat.

listaus 5
https://play.golang.org/p/BnVEHRCcdh

01 func waitForTask() {02 ch := make(chan string)0304 go func() {05 p := <-ch0607 // Employee performs work here.0809 // Employee is done and free to go.10 }()1112 time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)1314 ch <- "paper"15 }

rivillä 02 luettelossa 5 luodaan puskuroimaton kanava, jonka attribuutti on string data lähetetään signaalin mukana. Sitten linjalla 04 työntekijä palkataan ja käsketään odottamaan signaalia linjalla 05 ennen työnsä tekemistä. Linja 05 on kanava vastaanottaa, jolloin työntekijä estää odottaessaan pala paperia lähetät. Kun paperi on saatu työntekijältä, työntekijä tekee työn ja sitten on tehty ja vapaa menemään.

sinä johtajana työskentelet samanaikaisesti uuden työntekijäsi kanssa. Joten kun olet palkannut työntekijän linjalla 04, löydät itsesi (linjalla 12) tekemässä mitä sinun täytyy tehdä eston purkamiseksi ja signaalin työntekijälle. Huomaa, se oli tuntematon, kuinka kauan se kestäisi valmistella tämän paperin sinun täytyy lähettää.

lopulta olet valmis antamaan merkin työntekijälle. Linjalla 14 suoritetaan signaali datalla, joka on tuo paperinpala. Koska käytössä on puskuroimaton kanava, saat takuun siitä, että työntekijä on saanut paperin, kun lähetys on suoritettu. Vastaanottaminen tapahtuu ennen lähettämistä.

teknisesti tiedät vain, että paperi on työntekijällä siihen mennessä, kun kanavasi lähetys-operaatio on valmis. Molempien kanavaoperaatioiden jälkeen scheduler voi halutessaan suorittaa minkä tahansa lausuman. Seuraava rivi koodia, joka suoritetaan joko sinä tai työntekijä on nondeterministinen. Tämä tarkoittaa, että käyttämällä tulostaa lausuntoja voi huijata sinua noin asioiden järjestyksessä.

skenaario 2-odota tulosta

tässä seuraavassa skenaariossa asiat ovat toisin päin. Tällä kertaa haluat uuden työntekijän suorittamaan tehtävän heti, kun heidät palkataan, ja sinun täytyy odottaa työn tulosta. Sinun täytyy odottaa, koska tarvitset paperin heiltä ennen kuin voit jatkaa.

listaus 6
https://play.golang.org/p/VFAWHxIQTP

01 func waitForResult() {02 ch := make(chan string)0304 go func() {05 time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)0607 ch <- "paper"0809 // Employee is done and free to go.10 }()1112 p := <-ch13 }

rivillä 02 luettelossa 6 luodaan puskuroimaton kanava, jonka attribuutti on string data lähetetään signaalin mukana. Sitten linjalla 04 palkataan työntekijä, joka laitetaan heti töihin. Kun olet palkannut työntekijän linjalla 04, löydät itsesi seuraavana linjalla 12 odottamassa paperiraporttia.

kun työntekijä on saanut työn valmiiksi linjalla 05, hän lähettää tuloksen sinulle linjalla 07 tekemällä kanavalähetyksen datalla. Koska tämä on puskuroimaton kanava, vastaanottaminen tapahtuu ennen lähettämistä ja työntekijälle taataan, että olet saanut tuloksen. Kun työntekijällä on tämä takuu, ne on tehty ja vapaa menemään. Tässä skenaariossa, sinulla ei ole aavistustakaan, kuinka kauan se on menossa kestää työntekijä loppuun tehtävän.

kustannus / hyöty

puskuroimaton kanava takaa lähetettävän signaalin vastaanottamisen. Tämä on hienoa, mutta mikään ei ole ilmaista. Takuun hinta ei ole tiedossa. Työtehtävän odotustilanteessa työntekijällä ei ole aavistustakaan, kauanko paperin lähettäminen kestää. Tulosodotuksessa et tiedä, kauanko työntekijältä kestää lähettää tuo tulos.

kummassakin skenaariossa tämän tuntemattoman viiveen kanssa on elettävä, koska takuuta tarvitaan. Logiikka ei toimi ilman tätä taattua käytöstä.

signaali datalla-Ei Takuupuskuroituja kanavia >1

kun sinun ei tarvitse tietää, että lähetetty signaali on vastaanotettu, nämä kaksi skenaariota tulevat peliin: Fan Out ja Drop.

Puskuroidussa kanavassa on hyvin määritelty tila, jota voidaan käyttää lähetettävän tiedon tallentamiseen. Miten päätät, kuinka paljon tilaa tarvitset? Vastaa näihin kysymyksiin:

  • onko minulla tarkkaan määritelty työmäärä suoritettavana?
    • kuinka paljon työtä on?
  • jos työntekijäni ei pysy perässä, Voinko hylätä uuden työn?
    • kuinka paljon erinomainen työ saa minut kapasiteettiin?
  • minkä riskin olen valmis hyväksymään, jos ohjelmani päättyy yllättäen?
    • kaikki puskurissa odottava katoaa.

jos nämä kysymykset eivät ole järkeä käyttäytymistä olet mallinnus, se on koodi haju, että käyttämällä puskuroitu kanava mitään suurempi kuin 1 on luultavasti väärin.

Skenaario 1-Fan Out

fan out-kuvio mahdollistaa hyvin määritellyn määrän työntekijöitä, jotka työskentelevät samanaikaisesti. Koska sinulla on yksi työntekijä jokaista tehtävää varten, tiedät tarkalleen, kuinka monta raporttia saat. Voit varmistaa, että laatikossasi on oikea määrä tilaa saada kaikki nämä raportit. Tämä on etu työntekijäsi ei tarvitse odottaa sinua lähettämään raporttinsa. He kuitenkin tarvitse kukin vuorollaan saattamalla raportin ruutuun, jos ne saapuvat ruutuun tai lähes samaan aikaan.

kuvittele olevasi taas johtaja, mutta tällä kertaa palkkaat joukon työntekijöitä. Sinulla on yksilöllinen tehtävä, jonka haluat jokaisen työntekijän suorittavan. Kun jokainen yksittäinen työntekijä lopettaa tehtävänsä, heidän on annettava sinulle paperiraportti, joka on sijoitettava laatikkoon työpöydällesi.

listaus 7
https://play.golang.org/p/8HIt2sabs_

01 func fanOut() {02 emps := 2003 ch := make(chan string, emps)0405 for e := 0; e < emps; e++ {06 go func() {07 time.Sleep(time.Duration(rand.Intn(200)) * time.Millisecond)08 ch <- "paper"09 }()10 }1112 for emps > 0 {13 p := <-ch14 fmt.Println(p)15 emps--16 }17 }

rivillä 03 listauksessa 7 luodaan puskuroitu kanava, jonka attribuutti string data lähetetään signaalin mukana. Tällä kertaa kanava on luotu 20 puskurilla rivillä 02 ilmoitetun emps muuttujan ansiosta.

linjojen 05-10 välillä palkataan 20 työntekijää, jotka pääsevät heti töihin. Sinulla ei ole aavistustakaan, kuinka kauan kukin työntekijä aikoo ottaa linjan 07. Sitten linjalla 08 työntekijät lähettävät paperiraportin, mutta tällä kertaa lähetys ei estä vastaanottoa odottamasta. Koska ruudussa on tilaa jokaiselle työntekijälle, kanavan lähetys kilpailee vain muiden työntekijöiden kanssa, jotka saattavat haluta lähettää raporttinsa samaan aikaan tai lähes samaan aikaan.

rivien 12-16 välinen koodi on kaikki te. Tässä odotellaan, että kaikki 20 työntekijää saavat työnsä valmiiksi ja lähettävät raporttinsa. Linjalla 12, olet silmukka ja linjalla 13 olet estetty kanava vastaanottaa odottaa raportteja. Kun raportti on vastaanotettu, se tulostetaan riville 14 ja paikallinen laskurimuuttuja pienennetään osoittamaan, että työntekijä on tehnyt tehtävänsä.

skenaario 2-pudotus

pudotuskuvio mahdollistaa työn heittämisen pois, kun työntekijällä(työntekijöillä) on kapasiteettia. Tämän etuna on se, että jatkat työn vastaanottamista asiakkailtasi ja et koskaan käytä vastapainetta tai viivettä työn hyväksymisessä. Avain tässä on tietää, kun olet todella kapasiteetin niin et alle tai yli sitoutua työmäärä yrität saada aikaan. Yleensä integraatiotestaus tai mittarit ovat mitä tarvitset auttaa tunnistamaan tämän numeron.

Kuvittele, että olet taas johtaja ja palkkaat yhden työntekijän tekemään töitä. Sinulla on yksilöllinen tehtävä, jonka haluat työntekijän suorittavan. Kun työntekijä lopettaa tehtävänsä, et välitä tietää, että se on tehty. Tärkeää on vain se, voiko uusia töitä laittaa laatikkoon vai ei. Jos et pysty suorittamaan lähetystä, tiedät, että laatikko on täynnä ja työntekijä on kapasiteetissa. Tässä vaiheessa uusi työ on hylättävä, jotta asiat voivat jatkua.

listaus 8
https://play.golang.org/p/PhFUN5itiv

01 func selectDrop() {02 const cap = 503 ch := make(chan string, cap)0405 go func() {06 for p := range ch {07 fmt.Println("employee : received :", p)08 }09 }()1011 const work = 2012 for w := 0; w < work; w++ {13 select {14 case ch <- "paper":15 fmt.Println("manager : send ack")16 default:17 fmt.Println("manager : drop")18 }19 }2021 close(ch)22 }

rivillä 03 listauksessa 8 luodaan puskuroitu kanava, jonka attribuutti string data lähetetään signaalin mukana. Tällä kertaa kanava on luotu 5 puskurilla linjalla 02 ilmoitetun cap vakion ansiosta.

linjojen 05-09 väliin palkataan yksi työntekijä hoitamaan työtä. for range käytetään kanavan vastaanottoon. Aina kun paperinpala otetaan vastaan, se käsitellään linjalla 07.

rivien 11-19 välillä yrität lähettää työntekijällesi 20 paperinpalaa. Tällä kertaa select lausetta käytetään suorittamaan lähetys ensimmäisen case sisällä rivillä 14. Koska default lauseketta käytetään select sisällä rivillä 16, jos lähetys menee blokkiin, koska puskurissa ei ole enää tilaa, lähetyksestä luovutaan suorittamalla rivi 17.

lopuksi linjalla 21 kutsutaan kanavaa vasten sisäänrakennettu funktio close. Tämä viestittää ilman tietoja työntekijälle, että he ovat tehneet ja voivat vapaasti mennä, kun he ovat suorittaneet määrätyn työnsä..

kustannus / hyöty

puskuroitu kanava, joka on suurempi kuin 1, ei takaa, että lähetettävää signaalia koskaan vastaanotetaan. Tästä takuusta luopumisen etuna on se, että kahden goroutiinin välinen viestintä on viivästynyt tai sitä ei ole lainkaan. Fan Out-skenaariossa jokaiselle työntekijälle on puskuritila, joka lähettää raportin. Pudotusskenaariossa puskuri mitataan kapasiteetille ja jos kapasiteetti saavutetaan, työt pudotetaan, jotta asiat voivat pysyä liikkeessä.

molemmissa vaihtoehdoissa tämän takuun puuttumisen kanssa on elettävä, koska viiveen väheneminen on tärkeämpää. Vaatimus nollasta minimiin latenssista ei aiheuta ongelmia järjestelmän kokonaislogiikalle.

signaali Dataviivästetyllä Takuupuskuroidulla kanavalla 1

kun on tarpeen tietää, onko lähetetty edellinen signaali vastaanotettu ennen uuden signaalin lähettämistä, tulee mukaan tehtävien odotus-skenaario.

Skenaario 1-odota tehtäviä

tässä skenaariossa sinulla on uusi työntekijä, mutta he tekevät enemmän kuin vain yhden tehtävän. Syötät heille monia tehtäviä, yksi toisensa jälkeen. Heidän on kuitenkin tehtävä jokainen henkilökohtainen tehtävä loppuun ennen kuin he voivat aloittaa uuden tehtävän. Koska he voivat työskennellä vain yhdessä tehtävässä kerrallaan, työn luovutuksen välillä voi olla viiveongelmia. Jos viivettä voisi vähentää menettämättä takuuta siitä, että työntekijä on töissä seuraavassa tehtävässä, se voisi auttaa.

tässä kohtaa 1: n Puskuroidusta kanavasta on hyötyä. Jos kaikki sujuu odotetulla vauhdilla sinun ja työntekijän välillä, kummankaan ei tarvitse odottaa toista. Aina kun lähetät paperinpalan, puskuri on tyhjä. Aina kun työntekijä tavoittelee lisää töitä, puskuri on täynnä. Se on täydellinen työn virtauksen symmetria.

parasta on tämä. Jos yrität milloin tahansa lähettää paperinpalan, mutta et voi, koska puskuri on täynnä, tiedät työntekijälläsi olevan ongelma ja lopetat. Tässä kohtaa se viivästynyt takuu tulee kuvaan mukaan. Kun puskuri on tyhjä ja suoritat lähetyksen, sinulla on takuu siitä, että työntekijäsi on ottanut viimeisen lähettämäsi työn. Jos suoritat lähetyksen etkä pysty, sinulla on takuu, jota heillä ei ole.

listaus 9
https://play.golang.org/p/4pcuKCcAK3

01 func waitForTasks() {02 ch := make(chan string, 1)0304 go func() {05 for p := range ch {06 fmt.Println("employee : working :", p)07 }08 }()0910 const work = 1011 for w := 0; w < work; w++ {12 ch <- "paper"13 }1415 close(ch)16 }

rivillä 02 listauksessa 9 luodaan kokoluokaltaan 1 oleva puskuroitu kanava, jonka attribuutti string data lähetetään signaalin mukana. Linjojen 04-08 välillä työtä hoitamaan palkataan yksi työntekijä. for range käytetään kanavan vastaanottoon. Aina kun paperinpala otetaan vastaan, se käsitellään linjalla 06.

linjojen 10-13 välillä aletaan lähettää työtehtäviä työntekijälle. Jos työntekijäsi pystyy juoksemaan niin lujaa kuin pystyt lähettämään, viiveet välillänne vähenevät. Mutta jokaisen lähettää voit suorittaa onnistuneesti, sinulla on takuu siitä, että viimeinen pala työtä lähetit on työstetty.

lopuksi linjalla 15 kutsutaan kanavaa vasten sisäänrakennettu funktio close. Tämä viestii ilman dataa työntekijälle, että ne on tehty ja vapaa menemään. Viimeinen toimittamasi työ kuitenkin otetaan vastaan (huuhdellaan) ennen kuin for range lopetetaan.

signaali ilman dataa-Konteksti

tässä viimeisessä skenaariossa näet, miten voit peruuttaa käynnissä olevan goroutinen käyttämällä Context arvoa context paketista. Tämä kaikki toimii hyödyntämällä puskuroimaton kanava, joka on suljettu suorittaa signaalin ilman dataa.

olet johtaja viimeisen kerran ja palkkaat yhden työntekijän tekemään töitä. Tällä kertaa et ole valmis odottamaan jotain tuntematonta aikaa, että työntekijä valmistuu. Olet diskreetti deadline ja jos työntekijä ei lopeta ajoissa, et ole valmis odottamaan.

listaus 10
https://play.golang.org/p/6GQbN5Z7vC

01 func withTimeout() {02 duration := 50 * time.Millisecond0304 ctx, cancel := context.WithTimeout(context.Background(), duration)05 defer cancel()0607 ch := make(chan string, 1)0809 go func() {10 time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)11 ch <- "paper"12 }()1314 select {15 case p := <-ch:16 fmt.Println("work complete", p)1718 case <-ctx.Done():19 fmt.Println("moving on")20 }21 }

rivillä 02 listauksessa 10 ilmoitetaan kestoarvo, joka kuvaa sitä, kuinka kauan työntekijän on tehtävä loppuun. Tätä arvoa käytetään rivillä 04 luomaan context.Context arvo 50 millisekunnin aikalisällä. WithTimeout funktio context paketista palauttaa Context arvon ja peruutusfunktion.

context – paketissa luodaan goroutiini, joka sulkee Context – arvoon liittyvän Puskuroimattoman kanavan, kun kesto täyttyy. Olet vastuussa cancel – funktion kutsumisesta riippumatta siitä, miten asiat menevät. Tämä siivoaa Context: lle syntyneitä asioita. On ok, että cancel funktiota kutsutaan useammin kuin kerran.

rivillä 05 funktio cancel suoritetaan tämän funktion päätyttyä. Linjalla 07 luodaan 1 puskuroitu kanava, jota työntekijä käyttää lähettääkseen sinulle työnsä tuloksen. Sitten linjoilla 09-12 työntekijä palkataan ja laitetaan heti töihin. Et tiedä, kuinka kauan työntekijältä kestää valmistua.

linjojen 14-20 välillä käytetään select – lausetta kahden kanavan vastaanottamiseen. Vastaanottaa linjalla 15, odotat työntekijä lähettää Sinulle tuloksensa. Vastaanotossa rivillä 18 odotellaan, onko context – paketti merkki siitä, että 50 millisekuntia on kulunut. Kumpi signaali vastaanotat ensin on yksi käsitelty.

tärkeä osa tätä algoritmia on puskuroidun kanavan 1 käyttö. Jos työntekijä ei valmistu ajoissa, siirryt eteenpäin irtisanomatta työntekijää. Työntekijän näkökulmasta he lähettävät raportin aina linjalle 11, Ja he ovat sokeita, oletko siellä vai et vastaanottamassa sitä. Jos käytät suojaamatonta kanavaa, työntekijä estää ikuisesti yrittämästä lähettää raporttia, jos siirryt eteenpäin. Tämä aiheuttaisi goroutine-vuodon. Tämän estämiseksi käytetään siis 1: n puskuroitua kanavaa.

Conclusion

signaloinnin ominaisuudet takuiden, kanavan tilan ja lähettämisen ympärillä ovat tärkeitä tietää ja ymmärtää käytettäessä kanavia (tai samanaikaisuutta). Ne auttavat sinua toteuttamaan parasta käyttäytymistä tarvitset samanaikaisia ohjelmia ja algoritmeja kirjoitat. Ne auttavat sinua löytämään vikoja ja haistamaan mahdollisesti huonoa koodia.

tässä viestissä olen jakanut muutamia esimerkkiohjelmia, jotka osoittavat, miten signaloinnin ominaisuudet toimivat eri skenaarioissa. Jokaiseen sääntöön on poikkeuksia, mutta nämä kuviot ovat hyvä perusta aloittaa.

tarkastele näitä suuntaviivoja tiivistelmänä siitä, milloin ja miten kanavia voidaan tehokkaasti ajatella ja käyttää:

Kielimekaniikka

  • käytä kanavia goroutiinien orkestrointiin ja koordinointiin.
    • keskity signalointiominaisuuksiin, älä tiedon jakamiseen.
    • signalointi datalla tai ilman dataa.
    • kyseenalaistaa niiden käytön jaetun tilan synkronointiin.
      • on tapauksia, joissa kanavat voivat olla tätä yksinkertaisempia, mutta aluksi kyseenalaisia.
  • Puskuroimattomat kanavat:
    • vastaanottaa tapahtuu ennen lähetystä.
    • hyöty: 100% takuu signaali on vastaanotettu.
    • kustannukset: Tuntematon viive, milloin signaali vastaanotetaan.
  • puskuroidut kanavat:
    • lähetä tapahtuu ennen vastaanottoa.
    • hyöty: vähentää signaloinnin välistä estoviivettä.
    • kustannukset: ei takuuta, kun signaali on vastaanotettu.
      • mitä suurempi puskuri, sitä pienempi takuu.
      • Puskuri 1 voi antaa yhden viivästyneen takuun lähettämisen.
  • Sulkukanavat:
    • sulkeutuminen tapahtuu ennen vastaanottoa (kuten puskuroitu).
    • signalointi ilman tietoa.
    • täydellinen merkintään peruutuksista ja määräajoista.
  • ei kanavia:
    • Lähetä ja vastaanota-lohko.
    • Sammuta signalointi
    • täydellinen nopeuden rajoittamiseen tai lyhytaikaisiin seisokkeihin.

Suunnittelufilosofia

  • jos jokin tietty lähetys kanavalla voi aiheuttaa lähettävän goroutiinin tukkeutumisen:
    • ei saa käyttää puskuroitua kanavaa, joka on suurempi kuin 1.
      • 1: tä suuremmilla puskureilla on oltava syy/mitat.
    • täytyy tietää, mitä tapahtuu, kun lähettävä goroutine blokkaa.
  • jos jokin tietty lähettää kanavalla ei aiheuta lähettävän goroutine estää:
    • sinulla on tarkka määrä puskureita kunkin lähettää.
      • Viuhkakuvio
    • puskurin maksimikapasiteetti on mitattu.
      • Pudotuskuvio
  • vähemmän on enemmän puskureilla.
    • älä ajattele suorituskykyä, kun ajattelet puskureita.
    • Puskurit voivat auttaa vähentämään signaloinnin välistä estoviivettä.
      • estoviiveen vähentäminen kohti nollaa ei välttämättä tarkoita parempaa läpimenoa.
      • jos yhden puskuri antaa riittävän hyvän läpimenon, pidä se.
      • Kysymyspuskurit, jotka ovat yhtä suurempia ja mittaavat koon mukaan.
      • Etsi pienin mahdollinen puskuri, joka antaa riittävän hyvän läpimenon.

Vastaa

Sähköpostiosoitettasi ei julkaista.