Takk For At Du Abonnerer

Introduksjon

Da jeg begynte å jobbe Med gos kanaler for første gang, gjorde jeg feilen å tenke på kanaler som datastruktur. Jeg så kanaler som en kø som ga automatisk synkronisert tilgang mellom goroutines. Denne strukturelle forståelsen fikk meg til å skrive mye dårlig og komplisert samtidig kode.

jeg lærte over tid at det er best å glemme hvordan kanaler er strukturert og fokusere på hvordan de oppfører seg. Så nå når det gjelder kanaler, tenker jeg på en ting: signalering. En kanal tillater en goroutine å signalisere en annen goroutine om en bestemt hendelse. Signalering er kjernen i alt du bør gjøre med kanaler. Å tenke på kanaler som signalmekanisme vil tillate deg å skrive bedre kode med veldefinert og mer presis oppførsel.

for å forstå hvordan signalering fungerer, må vi forstå dens tre attributter:

  • Leveringsgaranti
  • Stat
  • Med Eller Uten Data

disse tre attributtene jobber sammen for å skape en designfilosofi rundt signalering. Etter at jeg har diskutert disse attributtene, vil jeg gi en rekke kodeeksempler som viser signalering med disse attributtene brukt.

Leveringsgaranti

Leveringsgarantien er basert på ett spørsmål: «trenger jeg en garanti for at signalet sendt av en bestemt goroutine er mottatt?»

Med andre ord, gitt dette eksemplet i liste 1:

Liste 1

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

trenger sendingen goroutine en garanti for at paper blir sendt over kanalen på linje 05 ble mottatt av goroutine på linje 02 før du går videre?

Basert på svaret på dette spørsmålet, vil du vite hvilken av de to typer kanaler som skal brukes: Ubufret eller Bufret. Hver kanal gir en annen oppførsel rundt garantier for levering.

Figur 1: Leveringsgaranti

 Leveringsgaranti

Garantier er viktige, og hvis du ikke tror det, har jeg massevis av ting jeg vil selge deg. Selvfølgelig prøver jeg å lage en vits, men blir du ikke nervøs når du ikke har garantier i livet? Å ha en sterk forståelse av hvorvidt du trenger en garanti er avgjørende når du skriver samtidig programvare. Når vi fortsetter, lærer du hvordan du bestemmer deg.

Tilstand

oppførselen til en kanal påvirkes direkte av dens nåværende Tilstand. Tilstanden til en kanal kan være null, åpen eller lukket.

Oppføring 2 nedenfor viser hvordan du deklarerer eller plasserer en kanal i hver av disse tre statene.

Oppføring 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)

staten bestemmer hvordan send og motta operasjoner oppfører seg.

Signaler sendes og mottas via en kanal. Ikke si lese/skrive fordi kanaler ikke utfører I/O.

Figur 2 : Stat

Stat

når en kanal er i null-tilstand, vil forsøk på sending eller mottak på kanalen blokkere. Når en kanal er i åpen tilstand, kan signaler sendes og mottas. Når en kanal er plassert i lukket tilstand, kan signaler ikke lenger sendes, men det er fortsatt mulig å motta signaler.

disse statene vil gi de forskjellige oppføringene du trenger for de forskjellige situasjonene du møter. Når du kombinerer Tilstand med Leveringsgaranti, kan du begynne å analysere kostnadene / fordelene du pådrar deg som følge av designvalgene dine. I mange tilfeller vil du også raskt kunne oppdage feil bare ved å lese koden, fordi du forstår hvordan kanalen skal oppføre seg.

Med Og Uten Data

det siste signalattributtet som må tas i betraktning, er om du trenger å signalisere med eller uten data.

du signaliserer med data ved å sende på en kanal.

Oppføring 3

01 ch <- "paper"

når du signaliserer med data, er det vanligvis fordi:

  • en goroutine blir bedt om å starte en ny oppgave.
  • en goroutine rapporterer tilbake et resultat.

du signaliserer uten data ved å lukke en kanal.

Oppføring 4

01 close(ch)

når du signaliserer uten data, er det vanligvis fordi:

  • en goroutine blir fortalt å stoppe hva de gjør.
  • en goroutine rapporterer tilbake at de er ferdige uten resultat.
  • en goroutine rapporterer at den har fullført behandling og stengt.

det er unntak fra disse reglene,men disse er de store brukssakene og de vi vil fokusere på i dette innlegget. Jeg vil vurdere unntak fra disse reglene for å være en første kode lukt.

en fordel med signalering uten data er at en enkelt goroutin kan signalisere mange goroutiner samtidig. Signalering med data er alltid en 1 til 1 utveksling mellom goroutines.

Signalering Med Data

når du skal signalisere med data, er det tre kanalkonfigurasjonsalternativer du kan velge avhengig av hvilken type garanti du trenger.

Figur 3 : Signalering Med Data

de tre kanalalternativene Er Ubufret, Bufret > 1 eller Bufret =1.

  • Garanti

    • en ubufret kanal gir Deg En Garanti for at et signal som sendes er mottatt.
      • Fordi Mottak av signalet Skjer Før Sendingen av signalet fullføres.
  • Ingen Garanti

    • En Bufret kanal av størrelse > 1 gir deg Ingen Garanti for at et signal som sendes er mottatt.
      • Fordi Sendingen av signalet Skjer Før mottak av signalet fullføres.
  • Forsinket Garanti

    • En Bufret kanal av størrelse =1 gir Deg En Forsinket Garanti. Det kan garantere at det forrige signalet som ble sendt, er mottatt.
      • Fordi Mottak Av Det Første Signalet, Skjer Før Sendingen av Det Andre Signalet fullføres.

størrelsen på bufferen må aldri være et tilfeldig tall, det må alltid beregnes for noen veldefinerte begrensninger. Det er ingen uendelig i databehandling, alt må ha noen veldefinerte begrensninger om det er tid eller rom.

Signalering Uten Data

Signalering uten data er hovedsakelig reservert for kansellering. Det gjør at en goroutine å signalisere en annen goroutine å avbryte hva de gjør og gå videre. Avbestilling kan implementeres ved hjelp Av Både Ubufrede og Bufrede kanaler, men ved Hjelp Av En Bufret kanal når ingen data vil bli sendt er en kode lukt.

Figur 4 : Signalering Uten Data

den innebygde funksjonen close brukes til å signalisere uten data. Som forklart ovenfor i Statsseksjonen, kan du fortsatt motta signaler pa en kanal som er stengt. Faktisk vil enhver mottak på en lukket kanal ikke blokkere og mottaksoperasjonen returnerer alltid.

i de fleste tilfeller vil du bruke standardbiblioteket context til å implementere signalering uten data. Pakken context bruker En Ubufret kanal under for signalering og den innebygde funksjonen close for å signalisere uten data.

hvis du velger å bruke din egen kanal for kansellering, i stedet for kontekstpakken, skal kanalen være av typen chan struct{}. Det er null-plass, idiomatisk måte å indikere en kanal som bare brukes til signalering.

Scenarier

med disse attributtene på plass, er den beste måten å forstå hvordan de fungerer i praksis, å kjøre gjennom en rekke kodescenarier. Jeg liker å tenke på goroutines som folk når jeg leser og skriver kanalbasert kode. Denne visualiseringen hjelper virkelig, og jeg vil bruke den som et hjelpemiddel nedenfor.

Signal Med Data-Garanti-Ubufrede Kanaler

når du trenger å vite at et signal som sendes, er mottatt, kommer to scenarier til spill. Disse Venter På Oppgave og Venter På Resultat.

Scenario 1-Vent På Oppgave

Tenk på å være en leder og ansette en ny ansatt. I dette scenariet vil du den nye ansatte til å utføre en oppgave, men de må vente til du er klar. Dette er fordi du trenger å gi dem et stykke papir før de starter.

Oppføring 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 }

på linje 02 i oppføring 5 opprettes En Ubufret kanal med attributtet at string data vil bli sendt med signalet. Så på linje 04, en ansatt er ansatt og beskjed om å vente på signalet på linje 05 før du gjør sitt arbeid. Linje 05 er kanalen mottar, forårsaker ansatt å blokkere mens du venter på stykke papir du vil sende. Når papiret er mottatt av den ansatte, utfører ansatt arbeidet og deretter er gjort og gratis å gå.

du som leder arbeider samtidig med din nye ansatt. Så når du ansetter ansatt på linje 04, finner du deg selv (på linje 12) gjør hva du trenger å gjøre for å oppheve blokkeringen og signal ansatt. Merk, det var ukjent hvor lang tid det ville ta å forberede dette stykke papir du må sende.

Til Slutt er du klar til å signalisere den ansatte. På linje 14 utfører du et signal med data, dataene er det stykke papir. Siden En Ubufret kanal blir brukt, får du en garanti for at den ansatte har mottatt papiret når sendingen er fullført. Mottak skjer før sending.

Teknisk alt du vet Er at den ansatte har papiret når kanalen sende operasjonen er fullført. Etter begge kanaloperasjoner kan planleggeren velge å utføre enhver setning den ønsker. Den neste kodelinjen som utføres enten av deg eller den ansatte, er ikke-deterministisk. Dette betyr at ved hjelp av print uttalelser kan lure deg om rekkefølgen på ting.

Scenario 2-Vent På Resultat

i dette neste scenariet reverseres ting. Denne gangen vil du at din nye medarbeider skal utføre en oppgave umiddelbart når de er ansatt, og du må vente på resultatet av deres arbeid. Du må vente fordi du trenger papiret fra dem før du kan fortsette.

Oppføring 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 }

på linje 02 i oppføring 6, opprettes En Ubufret kanal med attributtet at string data vil bli sendt med signalet. På linje 04 blir en ansatt ansatt og umiddelbart satt på jobb. Etter at du har ansatt ansatt på linje 04, finner du deg selv neste på linje 12 venter på papirrapporten.

når arbeidet er fullført av ansatt på linje 05, sender de resultatet til deg på linje 07 ved å utføre en kanal send med data. Siden dette er En Ubufret kanal, skjer mottak før sendingen, og den ansatte er garantert at du har mottatt resultatet. Når den ansatte har denne garantien, de er ferdig og gratis å gå. I dette scenariet har du ingen anelse om hvor lang tid det skal ta ansatt for å fullføre oppgaven.

Kostnad / Fordel

En Ubufret kanal gir en garanti for at et signal som sendes ble mottatt. Dette er flott, men ingenting er gratis. Kostnaden for denne garantien er ukjent latens. I Vente På Oppgaven scenariet har ansatt ingen anelse om hvor lang tid det kommer til å ta for deg å sende papiret. I Vente På Resultat scenario, har du ingen anelse om hvor lang tid det kommer til å ta ansatt å sende deg det resultatet.

i begge scenarier er denne ukjente latensen noe vi må leve med fordi garantien er nødvendig. Logikken virker ikke uten denne garanterte oppførselen.

Signal Med Data – Ingen Garanti-Bufrede Kanaler >1

Når du ikke trenger å vite at et signal som sendes, er mottatt, kommer disse to scenariene til spill: Vift ut og Slipp.

En Bufret kanal har et veldefinert mellomrom som kan brukes til å lagre dataene som sendes. Så hvordan bestemmer du hvor mye plass du trenger? Svar på disse spørsmålene:

  • har jeg en veldefinert mengde arbeid som skal fullføres?
    • hvor mye arbeid er det?
  • hvis min medarbeider ikke kan holde tritt, kan jeg kaste bort noe nytt arbeid?
    • Hvor mye fremragende arbeid setter meg på kapasitet?
  • Hvilken risiko er jeg villig til å akseptere hvis programmet avsluttes uventet?
    • alt som venter i bufferen vil gå tapt.

Hvis disse spørsmålene ikke gir mening for oppførselen du modellerer, er det en kodelukt at bruk av En Bufret kanal som er større enn 1, sannsynligvis er feil.

Scenario 1-Fan Out

et fan out-mønster lar deg kaste et veldefinert antall ansatte på et problem som jobber samtidig. Siden du har en ansatt for hver oppgave, vet du nøyaktig hvor mange rapporter du vil motta. Du kan sørge for at det er riktig mengde plass i boksen for å motta alle disse rapportene. Dette har fordelen av ansatte ikke trenger å vente for deg å sende inn sin rapport. De trenger imidlertid å hver ta en tur plassere rapporten i boksen hvis de kommer på boksen på eller nær samme tid.

Tenk deg at du er leder igjen, men denne gangen ansetter du et team av ansatte. Du har en individuell oppgave du vil at hver ansatt skal utføre. Når hver enkelt ansatt fullfører sin oppgave, må de gi deg en papirrapport som må plasseres i boksen på skrivebordet ditt.

Oppføring 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 }

på linje 03 i oppføring 7 opprettes en Bufret kanal med attributtet at string data vil bli sendt med signalet. Denne gangen er kanalen opprettet med 20 buffere takket være emps variabelen deklarert på linje 02.

mellom linjene 05 til 10, er 20 ansatte ansatt og de kommer umiddelbart til jobb. Du har ingen anelse om hvor lenge hver ansatt skal ta på linje 07. På linje 08 sender de ansatte papirrapporten, men denne gangen blokkerer ikke sendingen å vente på en mottak. Siden det er plass i boksen for hver ansatt, konkurrerer send på kanalen bare med andre ansatte som kanskje vil sende sin rapport på eller nær samme tid.

koden mellom linjene 12 til 16 er alt du. Det er her du venter på at alle 20 ansatte skal fullføre sitt arbeid og sende sin rapport. På linje 12, du er i en loop og på linje 13 du er blokkert i en kanal motta venter på rapportene. Når en rapport er mottatt, skrives rapporten på linje 14 og lokal teller variabelen er decremented å angi en ansatt er gjort.

Scenario 2-Drop

et dråpemønster lar deg kaste arbeid når dine ansatte er i kapasitet. Dette har fordelen av å fortsette å akseptere arbeid fra kundene dine og aldri bruke mottrykk eller latens i aksept av det arbeidet. Nøkkelen her er å vite når du er virkelig på kapasitet slik at du ikke under eller over forplikte seg til hvor mye arbeid du vil forsøke å få gjort. Vanligvis er integrasjonstesting eller beregninger det du trenger for å hjelpe deg med å identifisere dette nummeret.

Tenk deg at du er lederen igjen, og du ansetter en enkelt ansatt for å få arbeidet gjort. Du har en individuell oppgave du vil at den ansatte skal utføre. Som ansatt fullfører sin oppgave, bryr du deg ikke om å vite at de er ferdige. Alt som er viktig er om du kan eller ikke kan plassere nytt arbeid i boksen. Hvis du ikke kan utføre sendingen, vet du at boksen din er full og den ansatte er i kapasitet. På dette punktet må det nye arbeidet kastes slik at ting kan fortsette å bevege seg.

Oppføring 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 }

på linje 03 i oppføring 8 opprettes en Bufret kanal med attributtet at string data vil bli sendt med signalet. Denne gangen er kanalen opprettet med 5 buffere takket være cap konstant deklarert på linje 02.

mellom linjene 05 til 09 ansettes en enkelt ansatt for å håndtere arbeidet. En for range brukes for kanalen mottar. Hver gang et stykke papir mottas, behandles det på linje 07.

mellom linjene 11 til 19 prøver du å sende 20 stykker papir til din ansatt. Denne gangen brukes en select – setning til å utføre sendingen i den første case på linje 14. Siden default – klausulen brukes i select på linje 16, hvis sendingen skal blokkere fordi det ikke er mer plass i bufferen, blir sendingen forlatt ved å utføre linje 17.

Endelig på linje 21 kalles den innebygde funksjonen close mot kanalen. Dette vil signalere uten data til den ansatte de er ferdige og fri til å gå når de har fullført sitt tildelte arbeid..

Kostnad / Fordel

En Bufret kanal større enn 1 gir ingen garanti for at et signal som sendes, blir mottatt. Det er en fordel å gå bort fra denne garantien, som er redusert eller ingen ventetid i kommunikasjonen mellom to goroutiner. I Fan Out-scenariet er det en bufferplass for hver ansatt som skal sende en rapport. I Drop-scenariet måles bufferen for kapasitet, og hvis kapasiteten er nådd, faller arbeidet slik at ting kan fortsette å bevege seg.

i begge alternativene er denne mangelen på garanti noe vi må leve med fordi reduksjonen i latens er viktigere. Kravet om null til minimum latens utgjør ikke et problem for systemets generelle logikk.

Signal Med Data-Forsinket Garanti-Bufret Kanal 1

Når det er nødvendig å vite om det forrige signalet som ble sendt, er mottatt før du sender et nytt signal, Kommer Vent På Oppgaver-scenariet inn i spill.

Scenario 1-Vent På Oppgaver

I dette scenariet har du en ny ansatt, men de skal gjøre mer enn bare en oppgave. Du kommer til å mate dem mange oppgaver, den ene etter den andre. De må imidlertid fullføre hver enkelt oppgave før de kan starte en ny. Siden de bare kan jobbe med en oppgave om gangen, kan det være latensproblemer mellom arbeidet. Hvis ventetiden kan reduseres uten å miste garantien om at arbeidstakeren jobber med neste oppgave, kan det hjelpe.

dette er hvor En Bufret kanal på 1 har fordel. Hvis alt kjører i forventet tempo mellom deg og den ansatte, må ingen av dere vente på den andre. Hver gang du sender et stykke papir, er bufferen tom. Hver gang din medarbeider kommer til mer arbeid, er bufferen full. Det er en perfekt symmetri av arbeidsflyten.

den beste delen er dette. Hvis du når som helst prøver å sende et stykke papir, og du ikke kan fordi bufferen er full, vet du at din ansatt har et problem, og du stopper. Det er her den forsinkede garantien kommer inn. Når bufferen er tom og du utfører sendingen, har du garanti for at din ansatt har tatt det siste arbeidet du sendte. Hvis du utfører sendingen og du ikke kan, har du garantien de ikke har.

Oppføring 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 }

på linje 02 i oppføring 9 opprettes En Bufret kanal av størrelse 1 med attributtet at string data vil bli sendt med signalet. Mellom linjene 04 til 08 er en enkelt ansatt ansatt for å håndtere arbeidet. En for range brukes for kanalen mottar. Hver gang et stykke papir mottas, behandles det på linje 06.

mellom linjene 10 til 13 begynner du å sende oppgavene dine til den ansatte. Hvis medarbeideren din kan løpe så fort du kan sende, reduseres ventetiden mellom dere to. Men med hver sending du utfører vellykket, har du garanti for at det siste arbeidet du sendte inn, blir jobbet på.

Endelig på linje 15 kalles den innebygde funksjonen close mot kanalen. Dette vil signalere uten data til den ansatte de er ferdige og fri til å gå. Det siste arbeidet du sendte inn, vil imidlertid bli mottatt (spylt) før for range avsluttes.

Signal Uten Data-Kontekst

i dette siste scenariet vil du se hvordan du kan avbryte en kjørende goroutine ved hjelp av en Context – verdi fra context – pakken. Alt dette fungerer ved å utnytte En Ubufret kanal som er lukket for å utføre et signal uten data.

du er lederen en siste gang, og du ansetter en enkelt ansatt for å få arbeidet gjort. Denne gangen er du ikke villig til å vente på noe ukjent tid for den ansatte å fullføre. Du er på en diskret frist, og hvis ansatt ikke er ferdig i tide, er du ikke villig til å vente.

Oppføring 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 }

på linje 02 i oppføring 10 deklareres en varighetsverdi som representerer hvor lenge ansatt må fullføre oppgaven. Denne verdien brukes på linje 04 for å opprette en context.Context – verdi med en tidsavbrudd på 50 millisekunder. Funksjonen WithTimeout fra pakken context returnerer en verdi Context og en avbestillingsfunksjon.

context – pakken oppretter en goroutine som lukker Den Ubufrede kanalen som er knyttet til Context – verdien når varigheten er oppfylt. Du er ansvarlig for å ringe funksjonen cancel uansett hvordan ting går ut. Dette vil rydde opp ting som er opprettet for Context. Det er ok for cancel – funksjonen å bli kalt mer enn en gang.

på linje 05 blir funksjonen cancel utsatt for å bli utført når denne funksjonen avsluttes. På linje 07 Opprettes En Bufret kanal på 1, som skal brukes av den ansatte til å sende deg resultatet av sitt arbeid. Deretter på linje 09 til 12, er ansatt ansatt og umiddelbart satt på jobb. Du aner ikke hvor lang tid det vil ta den ansatte å fullføre.

mellom linjene 14 til 20 bruker du select – setningen for å motta på to kanaler. Motta på linje 15, du venter på at den ansatte skal sende deg resultatet. Motta på linje 18, du venter på å se om pakken context skal signalere at 50 millisekunder er oppe. Uansett hvilket signal du mottar først, blir det behandlet.

et viktig aspekt ved denne algoritmen er bruken av Den Bufrede kanalen til 1. Hvis den ansatte ikke er ferdig i tide, går du videre uten å gi den ansatte noen varsel. Fra ansattes perspektiv vil de alltid sende deg rapporten på linje 11, og de er blinde hvis du er der eller ikke mottar den. Hvis du bruker En Ubufret kanal, vil den ansatte blokkere for alltid å prøve å sende deg rapporten hvis du går videre. Dette ville skape en goroutine lekkasje. Så En Bufret kanal på 1 blir brukt for å forhindre at dette skjer.

Konklusjon

attributtene for signalering rundt garantier, kanaltilstand og sending er viktig å vite og forstå når du bruker kanaler (eller samtidighet). De vil hjelpe deg med å implementere den beste oppførselen du trenger for samtidige programmer og algoritmer du skriver. De vil hjelpe deg med å finne feil og snuse ut potensielt dårlig kode.

I dette innlegget har jeg delt noen eksempler på programmer som viser hvordan egenskapene til signalering fungerer i ulike scenarier. Det finnes unntak for hver regel, men disse mønstrene er et godt grunnlag for å starte.

Se gjennom disse skissene som et sammendrag av når og hvordan du effektivt kan tenke på og bruke kanaler:

Språkmekanikk

  • Bruk kanaler til å orkestrere og koordinere goroutiner.
    • Fokus på signalattributter og ikke deling av data.
    • Signalering med data eller uten data.
    • Spørsmål deres bruk for synkronisering av tilgang til delt tilstand.
      • det er tilfeller der kanaler kan være enklere for dette, men i utgangspunktet spørsmålet.
  • Ubufrede kanaler:
    • Motta skjer før Sendingen.
    • Fordel: 100% garanti signalet er mottatt.
    • Kostnad: Ukjent ventetid på når signalet vil bli mottatt.
  • Bufrede kanaler:
    • Send skjer før Mottak.
    • Fordel: Reduser blokkering av ventetid mellom signalering.
    • Kostnad: ingen garanti når signalet er mottatt.
      • jo større bufferen er, desto mindre garanti.
      • Buffer på 1 kan gi deg en forsinket sending av garanti.
  • Lukkekanaler:
    • Lukk skjer før Mottak (Som Bufret).
    • Signalering uten data.
    • Perfekt For kansellering av signaler og tidsfrister.
  • null kanaler:
    • Sende og Motta blokk.
    • Slå av signalering
    • Perfekt For hastighetsbegrensende eller kortsiktige stopp.

Designfilosofi

  • hvis en gitt Sending på en kanal kan føre til at sendingen goroutine blokkerer:
    • Ikke tillatt å bruke En Bufret kanal større enn 1.
      • Buffere større enn 1 må ha grunn / målinger.
    • Må vite hva som skjer når sende goroutine blokker.
  • Hvis en gitt Sending på en kanal ikke vil føre til at sendingen goroutine blokkerer:
    • du har nøyaktig antall buffere for hver sending.
      • Vift ut mønster
    • du har bufferen målt for maks kapasitet.
      • Slipp mønster
  • Mindre er mer med buffere.
    • ikke tenk på ytelse når du tenker på buffere.
    • Buffere kan bidra til å redusere blokkering av ventetid mellom signalering.
      • Å Redusere blokkeringsforsinkelse mot null betyr ikke nødvendigvis bedre gjennomstrømning.
      • hvis en buffer av en gir deg god nok gjennomstrømning, så hold den.
      • Spørsmålsbuffere som er større enn en og måler for størrelse.
      • Finn den minste mulige bufferen som gir god nok gjennomstrømning.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.