Köszönjük, hogy feliratkozott

Bevezetés

amikor először kezdtem el dolgozni a Go csatornáival, elkövettem azt a hibát, hogy a csatornákra mint adatstruktúrára gondoltam. A csatornákat olyan sorként láttam, amely automatikus szinkronizált hozzáférést biztosított a goroutines között. Ez a strukturális megértés sok rossz és bonyolult egyidejű kódot írt.

az idő múlásával megtanultam, hogy a legjobb, ha elfelejtjük a csatornák felépítését, és arra koncentrálunk, hogyan viselkednek. Tehát most, amikor a csatornákról van szó, egy dologra gondolok: jelzés. A csatorna lehetővé teszi az egyik goroutine számára, hogy jelezzen egy másik goroutine-t egy adott eseményről. A jelzés a lényege mindennek, amit a csatornákkal kell tennie. A csatornákra, mint jelzőmechanizmusra gondolva jobb kódot írhat jól definiált és pontosabb viselkedéssel.

ahhoz, hogy megértsük, hogyan működik a jelzés, meg kell értenünk annak három tulajdonságát:

  • Szállítási Garancia
  • állapot
  • adatokkal vagy anélkül

ez a három attribútum együtt dolgozik, hogy létrehozzon egy tervezési filozófiát a jelzés körül. Miután megvitattam ezeket az attribútumokat, számos olyan kódpéldát fogok bemutatni, amelyek bemutatják a jelzést ezekkel az attribútumokkal.

Szállítási Garancia

a Szállítási Garancia egy kérdésen alapul: “szükségem van garanciára, hogy egy adott goroutine által küldött jel érkezett?”

más szóval, ezt a példát az 1. listában:

lista 1

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

szüksége van-e a küldő goroutine-nak garanciára, hogy a paper – et a csatornán keresztül a 05-ös vonalon küldték el a goroutine a 02-es vonalon, mielőtt továbblépne?

a kérdésre adott válasz alapján tudni fogja, hogy a kétféle csatorna közül melyiket használja: nem pufferelt vagy pufferelt. Minden csatorna eltérő viselkedést biztosít a kézbesítési garanciák körül.

1.ábra : Szállítási Garancia

Szállítási Garancia

a garanciák fontosak, és ha nem gondolja, van egy csomó dolog, amit el akarok adni neked. Természetesen próbálok viccelődni, de nem ideges, ha nincs garancia az életben? Miután egy erős megértése, hogy szükség van-e a garancia elengedhetetlen írásakor egyidejű szoftver. Ahogy folytatjuk, megtanulod, hogyan kell dönteni.

állapot

a csatorna viselkedését közvetlenül befolyásolja a jelenlegi állapota. A csatorna állapota lehet nulla, nyitott vagy zárt.

az alábbi 2.lista bemutatja, hogyan lehet csatornát deklarálni vagy elhelyezni e három állapot mindegyikébe.

felsorolás 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)

az állapot határozza meg, hogyan viselkednek a küldés és fogadás műveletek.

a jeleket egy csatornán keresztül küldik és fogadják.

2.ábra : állapot

állapot

amikor egy csatorna nulla állapotban van, a csatornán megkísérelt küldés vagy fogadás blokkolódik. Amikor egy csatorna nyitott állapotban van, jeleket lehet küldeni és fogadni. Amikor egy csatorna zárt állapotba kerül, a jelek már nem küldhetők, de a jelek fogadása továbbra is lehetséges.

ezek az állapotok biztosítják a különböző viselkedéseket, amelyekre szüksége van a különböző helyzetekben. Ha az államot a szállítási garanciával kombinálja, elkezdheti elemezni a tervezési döntések eredményeként felmerülő költségeket/előnyöket. Sok esetben a kód elolvasásával gyorsan észlelheti a hibákat is, mert megérti, hogyan fog viselkedni a csatorna.

adatokkal és anélkül

az utolsó jelátviteli attribútum, amelyet figyelembe kell venni, az, hogy adatokkal vagy anélkül kell-e jelezni.

jelzéssel adatok végrehajtásával egy send egy csatornán.

felsorolás 3

01 ch <- "paper"

amikor adatokkal jelez, ez általában azért van, mert:

  • egy gorutint kérnek egy új feladat elindítására.
  • egy gorutin jelentést készít egy eredményről.

a csatorna bezárásával adat nélkül jelezhet.

Felsorolás 4

01 close(ch)

amikor adat nélkül jelez, általában azért van, mert:

  • a gorutin azt mondják, hogy hagyja abba, amit csinálnak.
  • a goroutine beszámol arról, hogy eredmény nélkül végeztek.
  • egy gorutin azt jelenti, hogy befejezte a feldolgozást és leállt.

vannak kivételek e szabályok alól, de ezek a legfontosabb felhasználási esetek, amelyekre ebben a bejegyzésben összpontosítunk. E szabályok alóli kivételeket kezdeti kódszagnak tekinteném.

az adatok nélküli jelzés egyik előnye, hogy egyetlen goroutin egyszerre sok goroutint képes jelezni. Az adatokkal történő jelzés mindig 1-1-es csere a goroutinok között.

jelzés adatokkal

ha adatokkal kíván jelezni, három csatornakonfigurációs lehetőség közül választhat a szükséges garancia típusától függően.

3. ábra : Jelzés adatokkal

a három csatorna opció nem pufferelt, pufferelt >1 vagy pufferelt =1.

  • garancia

    • a nem pufferelt csatorna garantálja, hogy a küldött jel érkezett.
      • mert a jel vétele a jel küldésének befejezése előtt történik.
  • nincs garancia

    • a > 1 méretű pufferelt csatorna nem garantálja, hogy a küldött jel érkezett.
      • mert a jel küldése a jel vétele előtt történik.
  • késleltetett garancia

    • a =1 méretű pufferelt csatorna késleltetett garanciát ad. Garantálhatja, hogy az előző küldött jel érkezett.
      • mivel az első jel vétele még a második jel küldése előtt megtörténik.

a puffer mérete soha nem lehet véletlen szám, mindig ki kell számítani valamilyen jól meghatározott kényszerre. A számítástechnikában nincs végtelen, mindennek rendelkeznie kell valamilyen jól meghatározott korlátozással, legyen az idő vagy tér.

adat nélküli jelzés

az adat nélküli jelzés elsősorban törlésre van fenntartva. Ez lehetővé teszi, hogy az egyik goroutine jelezzen egy másik goroutine-nak, hogy törölje azt, amit csinál, és lépjen tovább. A Törlés mind puffer nélküli, mind pufferelt csatornákkal megvalósítható, de pufferelt csatorna használata, ha nem küldünk adatokat, kódszag.

4. ábra : Jelzés adatok nélkül

a close beépített funkció adat nélküli jelzésre szolgál. Amint azt az állapot szakaszban fentebb kifejtettük, továbbra is fogadhat jeleket egy zárt csatornán. Valójában a zárt csatornán történő fogadás nem fog blokkolni, és a vételi művelet mindig visszatér.

a legtöbb esetben a standard library context csomagot szeretné használni az adatok nélküli jelzés megvalósításához. A context csomag alatta egy nem pufferelt csatornát használ a jelzéshez, a beépített close funkció pedig adat nélküli jelzéshez.

ha úgy dönt, hogy a saját csatornáját használja a törléshez a kontextuscsomag helyett, akkor a csatornájának chan struct{} típusúnak kell lennie. Ez a nulla tér, idiomatikus módszer a csak jelzésre használt csatorna jelzésére.

forgatókönyvek

ezekkel az attribútumokkal a legjobb módja annak, hogy jobban megértsük, hogyan működnek a gyakorlatban, ha végigfuttatunk egy sor kódforgatókönyvet. Szeretek a goroutinokra emberként gondolni, amikor csatorna alapú kódot olvasok és írok. Ez a vizualizáció valóban segít, és az alábbiakban segédeszközként fogom használni.

jel Adatgarancia – puffer nélküli csatornákkal

ha tudnia kell, hogy egy küldött jel érkezett, két forgatókönyv jön létre. Ezek várnak a feladatra és várnak az eredményre.

1.forgatókönyv – várjon a feladatra

gondoljon arra, hogy menedzser lesz, és új alkalmazottat vesz fel. Ebben az esetben azt szeretné, hogy az új alkalmazott elvégezzen egy feladatot, de meg kell várnia, amíg készen áll. Ez azért van, mert meg kell adni nekik egy darab papírt, mielőtt elkezdenék.

felsorolás 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 }

a 02. sorban az 5. listában egy nem pufferelt csatorna jön létre azzal az attribútummal, hogy string adatokat küld a jellel. Ezután a 04-es vonalon egy alkalmazottat felvesznek, és azt mondják, hogy várjon a jelre a 05-ös vonalon, mielőtt elvégezné a munkáját. A 05-ös vonal a csatorna fogadása, ami az alkalmazott blokkolását okozza, miközben várja az elküldött papírdarabot. Miután a munkavállaló megkapta a papírt, a munkavállaló elvégzi a munkát, majd elkészül és szabadon távozhat.

Ön, mint vezető, egyidejűleg dolgozik az új alkalmazottjával. Tehát miután felvette a munkavállalót a 04-es vonalon, találja magát (a 12-es vonalon), amit meg kell tennie, hogy feloldja és jelezze a munkavállalót. Megjegyzés, nem volt ismert, hogy mennyi ideig tart, hogy előkészítse ezt a darab papírt kell küldeni.

végül készen áll arra, hogy jelezze a munkavállalót. A 14-es vonalon egy adatot tartalmazó jelet hajt végre, az adat az a papírdarab. Mivel nem pufferelt csatornát használnak, garanciát kap arra, hogy a munkavállaló megkapta a papírt, miután a küldési művelet befejeződött. A fogadás a küldés előtt történik.

technikailag csak annyit tudsz, hogy az alkalmazottnak megvan a papírja, mire a csatornaküldési művelet befejeződik. Mindkét csatorna művelet után az ütemező választhat, hogy végrehajtja-e a kívánt utasítást. A következő kódsor, amelyet Ön vagy a munkavállaló hajt végre, nem determinisztikus. Ez azt jelenti, hogy a nyomtatott nyilatkozatok használata megtévesztheti a dolgok sorrendjét.

2.forgatókönyv – várakozás az eredményre

ebben a következő forgatókönyvben a dolgok megfordulnak. Ezúttal azt szeretné, hogy az új alkalmazott azonnal elvégezzen egy feladatot, amikor felveszik őket, és meg kell várnia a munkájuk eredményét. Meg kell várni, mert szüksége van a papír tőlük, mielőtt továbbra is.

felsorolás 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 }

a 02. sorban a 6. listában egy nem pufferelt csatorna jön létre azzal az attribútummal, hogy string adatokat küld a jellel. Ezután a 04-es vonalon egy alkalmazottat felvesznek, és azonnal munkába állítják. Miután felvette a munkavállalót a 04-es vonalon, a következő sorban találja magát 12 várja a papírjelentést.

miután a munkavállaló befejezte a munkát a 05-ös vonalon, elküldi az eredményt a 07-es vonalon egy csatornaküldés végrehajtásával. Mivel ez egy nem pufferelt csatorna, a fogadás a küldés előtt történik, és az alkalmazott garantálja, hogy megkapta az eredményt. Miután a munkavállaló megkapta ezt a garanciát, készen állnak és szabadon távozhatnak. Ebben a forgatókönyvben fogalma sincs arról, hogy mennyi időbe telik az alkalmazottnak a feladat befejezése.

költség/haszon

a nem pufferelt csatorna garantálja, hogy a küldött jel érkezett. Ez nagyszerű, de semmi sem ingyenes. A garancia költsége ismeretlen késleltetés. A várakozás a feladatra forgatókönyvben az alkalmazottnak fogalma sincs arról, hogy mennyi időbe telik, amíg elküldi ezt a papírt. Az eredmény várakozása forgatókönyvben fogalma sincs arról, hogy mennyi időbe telik az alkalmazottnak az eredmény elküldése.

mindkét esetben ezzel az ismeretlen késleltetéssel együtt kell élnünk, mert a garancia szükséges. A logika nem működik e garantált viselkedés nélkül.

jel adatokkal-nincs garancia-pufferelt csatornák >1

ha nem kell tudnia, hogy a küldött jel érkezett, akkor ez a két forgatókönyv jön létre: Fan Out and Drop.

a pufferelt csatorna jól meghatározott területtel rendelkezik, amely felhasználható az elküldött adatok tárolására. Tehát hogyan dönti el, hogy mennyi helyre van szüksége? Válaszoljon ezekre a kérdésekre:

  • van egy jól meghatározott mennyiségű munka, amelyet be kell fejeznem?
    • mennyi munka van?
  • ha a munkavállaló nem tud lépést tartani, tudok dobni minden új munkát?
    • mennyi kiemelkedő munka tesz engem kapacitássá?
  • milyen kockázatot vállalok, ha a programom váratlanul véget ér?
    • bármi, ami a pufferben vár, elvész.

ha ezeknek a kérdéseknek nincs értelme a modellezett viselkedésnek, akkor kódszag, hogy az 1-nél nagyobb pufferelt csatorna használata valószínűleg helytelen.

forgatókönyv 1 – Fan Out

a fan out minta lehetővé teszi, hogy dobja egy jól meghatározott számú alkalmazott a probléma, akik egyidejűleg dolgoznak. Mivel minden feladathoz egy alkalmazottja van, pontosan tudja, hány jelentést fog kapni. Meggyőződhet arról, hogy a dobozban megfelelő mennyiségű hely van-e az összes jelentés fogadásához. Ennek az az előnye, hogy alkalmazottainak nem kell megvárniuk a jelentés benyújtását. Mindazonáltal meg kell fordulniuk, ha a jelentést a dobozba helyezik, ha ugyanabban az időben vagy annak közelében érkeznek a dobozba.

Képzeld el, hogy újra vezető vagy, de ezúttal egy csapat alkalmazottat veszel fel. Van egy egyedi feladat, amelyet minden alkalmazottnak el kell végeznie. Mivel minden egyes alkalmazott befejezi feladatát, papíralapú jelentést kell benyújtania Önnek, amelyet az íróasztal dobozába kell helyezni.

felsorolás 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 }

a 03. sorban a 7. listában egy pufferelt csatorna jön létre azzal az attribútummal, hogy string adatokat küld a jellel. Ezúttal a csatorna 20 pufferrel jön létre a 02.sorban deklarált emps változónak köszönhetően.

a 05-től 10-ig terjedő sorok között 20 alkalmazottat vesznek fel, akik azonnal munkába állnak. Fogalmad sincs, mennyi ideig tart minden alkalmazott a 07-es vonalon. Ezután a 08. sorban az alkalmazottak elküldik a papírjelentést, de ezúttal a Küldés nem blokkolja a fogadás várakozását. Mivel minden alkalmazott számára van hely a dobozban, a csatornán történő küldés csak olyan alkalmazottakkal versenyez, akik esetleg ugyanabban az időben vagy annak közelében szeretnék elküldeni jelentésüket.

a 12-től 16-ig terjedő sorok közötti kód csak te vagy. Itt várja meg, hogy mind a 20 alkalmazott befejezze munkáját és elküldje jelentését. A 12-es vonalon hurokban vagy, a 13-as vonalon pedig blokkolva van egy csatorna fogadása, amely a jelentésekre vár. A jelentés beérkezése után a jelentés kinyomtatásra kerül a 14.sorban, és a helyi számláló változó csökken, jelezve, hogy egy alkalmazott elkészült.

2.forgatókönyv – csepp

a csepp minta lehetővé teszi, hogy dobja el a munkát, amikor a munkavállaló(k) a kapacitás. Ennek az az előnye, hogy továbbra is elfogadja az ügyfelek munkáját, és soha nem alkalmaz ellennyomást vagy késleltetést a munka elfogadásakor. A legfontosabb itt az, hogy tudjuk, mikor vagyunk valóban kapacitással, így nem vállaljuk, hogy mennyi munkát próbálunk elvégezni. Általában integrációs tesztelésre vagy mutatókra van szükség a szám azonosításához.

Képzeld el, hogy újra vezető vagy, és egyetlen alkalmazottat veszel fel a munka elvégzésére. Van egy egyedi feladat, amelyet a munkavállalónak végre kell hajtania. Amint a munkavállaló befejezi a feladatát, nem érdekli, hogy készen vannak-e. Csak az a fontos, hogy új munkát helyezhet-e a dobozba. Ha nem tudja végrehajtani a küldést, akkor tudja, hogy a doboz tele van, és az alkalmazott kapacitással rendelkezik. Ezen a ponton az új munkát el kell dobni, hogy a dolgok tovább mozoghassanak.

felsorolás 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 }

a 03. sorban a 8. listában egy pufferelt csatorna jön létre azzal az attribútummal, hogy string adatokat küld a jellel. Ezúttal a csatorna 5 pufferrel jön létre a 02-es vonalon deklarált cap állandónak köszönhetően.

a 05-09 sorok között egyetlen alkalmazottat vesznek fel a munka kezelésére. A for range a csatorna vételére szolgál. Minden alkalommal, amikor egy darab papírt kap, azt a 07-es vonalon dolgozzák fel.

a 11-től 19-ig terjedő sorok között 20 darab papírt próbál küldeni az alkalmazottjának. Ezúttal egy select utasítást használunk a Küldés végrehajtására az első case – en belül a 14.sorban. Mivel a default záradékot a select a 16.sorban használják, ha a Küldés blokkolni fog, mert nincs több hely a pufferben, a küldést a 17. sor végrehajtásával elhagyják.

végül a 21.sorban a beépített funkció close a csatorna ellen kerül meghívásra. Ez adat nélkül jelzi a munkavállalónak, hogy elvégezték és szabadon távozhatnak, miután befejezték a kijelölt munkát..

költség/haszon

az 1-nél nagyobb pufferelt csatorna nem garantálja, hogy az elküldött jelet valaha is fogadják. Van egy előnye, hogy elhagyja ezt a garanciát, ami a két goroutine közötti kommunikáció csökkent vagy nincs késleltetése. A Fan Out forgatókönyvben minden alkalmazott számára van egy pufferterület, amely jelentést küld. A leesési forgatókönyvben a puffert a kapacitás méri, és ha a kapacitás eléri a munkát, akkor a dolgok tovább mozoghatnak.

mindkét lehetőségnél a garancia hiányával együtt kell élnünk, mert a késleltetés csökkentése fontosabb. A nullától a minimális késleltetésig terjedő követelmény nem jelent problémát a rendszer általános logikájában.

adatjel – késleltetett garancia – pufferelt 1.csatorna

ha új jel küldése előtt tudni kell, hogy az előző küldött jel érkezett-e, akkor a feladatok várakozása forgatókönyv lép életbe.

1.forgatókönyv – feladatok várása

ebben a forgatókönyvben van egy új alkalmazott, de ők nem csak egy feladatot fognak elvégezni. Fogsz etetni őket sok feladat, egyik a másik után. Azonban minden egyes feladatot be kell fejezniük, mielőtt újat kezdhetnek. Mivel egyszerre csak egy feladaton tudnak dolgozni, késleltetési problémák merülhetnek fel a munka átadása között. Ha a késleltetés csökkenthető anélkül, hogy elveszítené a garanciát arra, hogy a munkavállaló a következő feladaton dolgozik, segíthet.

itt van az 1 pufferelt csatornájának előnye. Ha minden a várt ütemben halad közted és a munkavállaló között, egyiküknek sem kell várnia a másikra. Minden alkalommal, amikor egy darab papírt küld, a puffer üres. Minden alkalommal, amikor alkalmazottja több munkához jut, a puffer megtelt. Ez a munkafolyamat tökéletes szimmetriája.

a legjobb rész ez. Ha bármikor megpróbál küldeni egy darab papírt, és nem tudja, mert a puffer tele van, akkor tudja, hogy az alkalmazottnak problémája van, és abbahagyja. Itt jön be a késedelmes garancia. Ha a puffer üres, és végrehajtja a küldést, akkor garantálhatja, hogy alkalmazottja elvégezte az utoljára elküldött munkát. Ha végrehajtja a küldést, de nem tudja, akkor garantálja, hogy nem.

lista 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 }

a 02. sorban a 9. listában egy 1 méretű pufferelt csatorna jön létre azzal az attribútummal, hogy string adatokat küld a jellel. Sorok között 04 keresztül 08 egyetlen alkalmazottat vesznek fel a munka kezelésére. A for range a csatorna vételére szolgál. Minden alkalommal, amikor egy darab papírt kap, azt a 06-os vonalon dolgozzák fel.

a 10-től 13-ig terjedő sorok között elkezdi elküldeni a feladatokat az alkalmazottnak. Ha alkalmazottja olyan gyorsan tud futni, amennyit csak tud küldeni, akkor a kettő közötti késleltetés csökken. De minden küldéssel, amelyet sikeresen teljesít, garantálja, hogy az utolsó beküldött munkán dolgozik.

végül a 15.sorban a beépített funkció close a csatorna ellen kerül meghívásra. Ez adat nélkül jelzi a munkavállalónak, hogy készen állnak és szabadon távozhatnak. Az utolsó beküldött munka azonban a for range befejezése előtt beérkezik (kipirul).

Signal without Data – Context

ebben az utolsó forgatókönyvben láthatja, hogyan törölheti a futó goroutint a Context érték használatával a context csomagból. Mindez egy nem pufferelt csatorna kihasználásával működik, amely zárva van, hogy adat nélküli jelet hajtson végre.

utoljára te vagy a menedzser, és egyetlen alkalmazottat veszel fel a munka elvégzésére. Ezúttal nem hajlandó várni egy ismeretlen ideig, amíg a munkavállaló befejezi. Ön diszkrét határidőn belül van, és ha a munkavállaló nem fejezi be időben, akkor nem hajlandó várni.

felsorolás 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 }

a 02. sorban a 10. listában egy időtartam értéket deklarálnak, amely azt jelzi, hogy a munkavállalónak mennyi ideig kell befejeznie a feladatot. Ez az érték a 04-es sorban context.Context értéket hoz létre 50 milliszekundumos időkorláttal. A WithTimeout függvény a context csomagból egy Context értéket és egy törlési függvényt ad vissza.

a context csomag létrehoz egy goroutint, amely bezárja a Context értékkel társított nem pufferelt csatornát, amint az időtartam teljesül. Ön felelős a cancel függvény hívásáért, függetlenül attól, hogy a dolgok hogyan alakulnak. Ez megtisztítja a Contextszámára létrehozott dolgokat. Rendben van, ha a cancel függvényt többször is meghívják.

a 05-ös vonalon az cancel függvény végrehajtása elhalasztásra kerül, ha ez a funkció véget ér. A 07-es vonalon létrejön az 1-es pufferelt csatorna, amelyet az alkalmazott arra fog használni, hogy elküldje Önnek munkájuk eredményét. Ezután a 09-12-es vonalakon a munkavállalót felveszik és azonnal munkába állítják. Fogalmad sincs, mennyi időbe telik az alkalmazottnak befejezni.

a 14-től 20-ig tartó sorok között a select utasítást használja két csatornán történő fogadáshoz. A fogadás a 15. sorban várja meg, amíg a munkavállaló elküldi Önnek az eredményét. A fogadás a 18. sorban várja meg, hogy a context csomag jelzi-e, hogy az 50 milliszekundum lejárt. Bármelyik jelet is kapja meg először, az lesz a feldolgozott.

ennek az algoritmusnak fontos szempontja az 1 pufferelt csatornájának használata. Ha a munkavállaló nem fejezi be időben, akkor tovább lép, anélkül, hogy értesítést adna a munkavállalónak. Az alkalmazottak szemszögéből mindig elküldik a jelentést a 11. vonalon, és vakok, ha ott vagy, vagy nem kapják meg. Ha nem pufferelt csatornát használ, az alkalmazott örökre blokkolja a jelentés elküldését, ha továbblép. Ez gorutin szivárgást okozna. Tehát egy 1-es pufferelt csatornát használnak ennek megakadályozására.

következtetés

a garanciák, a csatornaállapot és a Küldés körüli jelzés attribútumait fontos tudni és megérteni a csatornák (vagy párhuzamosság) használatakor. Segítenek Önnek abban, hogy végrehajtsa a legjobb viselkedést, amire szüksége van az Ön által írt egyidejű programokhoz és algoritmusokhoz. Segítenek megtalálni a hibákat és kiszimatolni a potenciálisan rossz kódot.

ebben a bejegyzésben megosztottam néhány mintaprogramot, amelyek megmutatják, hogyan működnek a jelzés attribútumai különböző forgatókönyvekben. Minden szabály alól vannak kivételek, de ezek a minták jó alapot jelentenek a kezdéshez.

tekintse át ezeket a körvonalakat, hogy összefoglalja, mikor és hogyan kell hatékonyan gondolkodni és használni a csatornákat:

nyelvi mechanika

  • csatornákat használ a gorutinok hangszerelésére és koordinálására.
    • Fókuszban a jelátviteli attribútumok, nem pedig az adatok megosztása.
    • jelzés adatokkal vagy adatok nélkül.
    • megkérdőjelezik a megosztott állapothoz való hozzáférés szinkronizálásának használatát.
      • vannak olyan esetek, amikor a csatornák egyszerűbbek lehetnek ehhez, de kezdetben kérdés.
  • nem pufferelt csatornák:
    • a fogadás a küldés előtt történik.
    • előny: 100% – os garancia a jel fogadására.
    • költség: Ismeretlen késleltetés, amikor a jel érkezik.
  • pufferelt csatornák:
    • a Küldés a fogadás előtt történik.
    • előny: csökkentse a jelzés közötti blokkolási késleltetést.
    • költség: nincs garancia, ha a jel érkezett.
      • minél nagyobb a puffer, annál kevesebb a garancia.
      • puffer 1 adhat egy késleltetett küldési garancia.
  • csatornák bezárása:
    • a Bezárás A fogadás előtt történik (például pufferelt).
    • jelzés adat nélkül.
    • Tökéletes a törlések és határidők jelzésére.
  • nil csatornák:
    • Küldés és fogadás blokk.
    • kapcsolja ki a jelzést
    • tökéletes sebességkorlátozáshoz vagy rövid távú leállásokhoz.

tervezési filozófia

  • ha egy csatornán egy adott Küldés blokkolhatja a küldő goroutint:
    • nem használhat 1-nél nagyobb pufferelt csatornát.
      • az 1-nél nagyobb Puffereknek okkal/mérésekkel kell rendelkezniük.
    • tudnia kell, mi történik, ha a küldő goroutine blokkol.
  • ha egy adott Küldés egy csatornán nem okozza a küldő goroutine blokkolását:
    • megvan a pontos pufferek száma minden küldéshez.
      • ventilátor ki Minta
    • megvan a puffer mért maximális kapacitás.
      • csepp minta
  • a pufferekkel kevesebb több.
    • ne gondoljon a teljesítményre, amikor pufferekre gondol.
    • a pufferek segíthetnek csökkenteni a jelzés közötti blokkolási késleltetést.
      • a blokkolási késleltetés nullára csökkentése nem feltétlenül jelent jobb átviteli sebességet.
      • ha egy puffer elég jó teljesítményt nyújt, akkor tartsa meg.
      • kérdés pufferek, amelyek nagyobbak, mint egy, és intézkedés a méret.
      • keresse meg a lehető legkisebb puffert, amely elég jó teljesítményt nyújt.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.