

Recepty pre gorutiny a kanály -- worker pool | robonovotny
source link: https://novotnyr.github.io/scrolls/goroutines-vzory-pouzitie-3-worker-pool/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Minule sme vážili zvieratá na viacerých gorutinách. Ukážme si situáciu, keď máme worker pool, teda bank konkrétneho počtu gorutín, ktoré si vyberajú robotu zo spoločného frontu, spracovávajú a výsledky posielajú do nového spoločného frontu.
Začnime opäť vážiť zvieratá.
Kostra
V kostre si len vytvorme kanál pre zvieratá, do ktorého budeme posielať jedince súce na váženie.
Rovno povedzme, že toto skončí deadlockom.
1 | Nebufferovaný kanál, z ktorého si budú neskôr pracujúce gorutiny vyberať úlohy. |
2 | Pošleme doňho zvieratá. |
3 | Na konci kanál zavrieme. |
4 | Zavoláme funkciu, ktorá pošle údaje so zvieratami do komunikačného nebufferovaného kanála. |
Toto je samozrejme deadlock: z kanála nik nečíta a program obratom skončí.
Distribúcia práce
Distribuujme teraz prácu cez „manažéra“, ktorý bude čítať z kanála úloh a rozdeľovať prácu.
Na začiatku ju rozdelí sám sebe.
1 | Čítame z kanála, kým sa kanál neuzavrie a zvieratá len vypisujeme. |
Použitie v kóde? Dôležité je predísť deadlocku.
Keďže máme synchrónny nebufferovaný kanál, nemôžeme najprv posielať zvieratá na váženie a potom čakať na úlohy. To by bol jasný deadlock — producent by nemal konzumenta.
Nemôžeme to ani urobiť naopak, pretože by manažér-konzument čakal na producenta, ktorý by sa spustil až neskôr.
Rozseknime go-rdický uzol a spustime jednu z týchto súčiastok v gorutine — a zvoľme si za ňu funkciu, ktorá zaradí údaje do kanála.
1 | V gorutine pustíme „prúd“ zvierat, ktoré sa ocitnú v komunikačnom kanáli. |
2 | Začneme distribuovať prácu. |
Distribúcia práce vo funkcii Distribúcia práce
Deadlock však nenastáva — jednak pre komunikáciu medzi dvoma korutinami a zároveň kvôli jasnému explicitnému uzatvoreniu kanála. |
Robotníci pre tri gorutiny vo Worker Pool.
Začnime naozaj rozdeľovať prácu, a nielen simulovať!
Vytvorme si samostatnú funkciu pre robotnícku triedu, pardón, pre robotnícku funkciu.
Tá bude veľmi pomaly vážiť veľmi veľké zvieratá.
1 | Funkcia zoberie identifikátor (pre ladiace účely) a kanál, z ktorého bude načítavať zvieratá. |
2 | Zvieratá berieme z komunikačného kanála, kým sa kanál nezavrie. |
3 | Vážime a vypisujeme. |
Kto zatvára kanál? Producent, teda funkcia streamWork . To je dôležitá obrana proti deadlocku.
|
Upravme aj manažment:
1 | Spusťme tri — nie viac, nie menej — gorutiny. Pošlime im vstupný kanál. |
Gorutiny budú súperiť o zvieratá v komunikačnom kanáli. |
Spusťme firmu na zvieratá
Ak teraz spustíme main
, neuvidíme nič.
Povaha distributeWork
sa zmenila — už len vystrelí salvu gorutín, tak ako v predošlých životných situáciách, a okamžite skončí.
Keď to chceme urobiť hnusne, budeme čakať.
1 | Hnusne čakáme. |
Výstup pošle dve salvy za sekundu. Sekundu totiž trvá, kým každý worker
spracuje výsledok.
Čakanie je však škaredé.
Ak chceme čakať na dobehnutie manažéra, znamená to čakať na koniec gorutín.
Je teda čas na WaitGroup
.
1 | Pripravíme si WaitGroup s takým počtom gorutín, koľko máme robotníkov. |
2 | Spustíme v gorutine robotníka.
Použijeme vnorenú funkciu, do ktorej dopravíme identifikátor robotníka cez parameter, pretože využívame premennú i z iterácie. |
3 | Keď robotník skončí, znížime počítadlo vo WaitGroup . |
4 | Čakáme, kým dobehnú všetky gorutiny. |
Takto už nemusíme škaredo čakať:
Program skončí zhruba po 2 sekundách, keď dobehnú obe salvy troch gorutín.
Váženie s výsledkami
Ak chceme, aby gorutiny komunikovali späť, použijeme recepty z predošlých dielov.
-
Funkcia
worker
bude posielať výsledky do samostatného kanála. -
Funkcia
distributeWork
bude čakať na výsledky. -
A vytvoríme samostatnú funkciu na agregáciu výsledných váh.
Robotníčky odpovedajú do kanála
1 | Očakávame tretí parameter: kanál pre navážené hmotnosti. |
2 | Každú hmotnosť zapíšeme do kanála. |
Agregácia výsledkov
Agregácia výsledkov načíta údaje a zlúči:
Distribúcia roboty prekopaná
Musíme prekopať distribúciu práce:
-
Zavedieme výstupný kanál.
-
Počkáme na výsledky.
-
Agregujeme.
1 | Vytvoríme kanál pre výstupné výsledky. |
2 | Robotnícka gorutina dostane výstupný kanál ako argument. |
3 | Čakáme na výsledky v samostatnej gorutine. Toto je presne vzor z predošlého dielu. |
4 | Ak dôjdu všetky dáta, agregujeme a výsledok vrátime z funkcie. |
Úprava hlavnej funkcie
Samozrejme, musíme upraviť aj hlavnú funkciu:
1 | Jednoducho rozdelíme robotu a získame výsledok. |
2 | Výsledok vypíšeme. |
Zhrnutie
To je všetko, robota sa veselo rozdeľuje!
Ak odstránime čakanie vo funkcii worker
, uvidíme priame a rýchle rátanie:
Vidíme, ako sa dáta tlačia do robotníkov: v tomto prípade prvý vybavil nosorožca, druhý odvážil slona, žirafu a veľrybu a posledný stihol hrocha a bizóna.
Bonus: Priamy výpis výsledkov
Ak chceme len priamy výpis výsledkov, kód sa zjednoduší.
Z agregácie je len výpis
Z agregácie stačí robiť výpis:
Distribúcia potrebuje výstupný kanál
Distribúcia výsledkov potrebuje niekoľko zmien:
1 | Žiadame aj výstupný kanál. |
2 | Čakáme na dobehnutie korutín. |
3 | Ak všetky korutiny dobehli, zatvárame výstupný kanál. |
Zatváranie a čakanie už nemusíme robiť v samostatnej korutine. Konzumovať budeme z inej korutiny, ktorá bude blokovať pri čítaní výsledkov. Deadlock nenastane, keďže |
Upravená funkcia main
Funkcia main
spustí trojicu aktérov:
-
zápis vstupných údajov pobeží v gorutine
-
rozdelenie roboty pobeží v samostatnej gorutine
-
čakanie na výsledky pobeží v hlavnej gorutine, kde súčasne blokuje predčasné ukončenie programu a zároveň blokuje pri čítaní z výsledkov.
1 | Vytvoríme kanál pre výsledky. |
2 | Pošleme ho do rozdeľovania roboty. |
3 | Spracovávame výsledky, kde blokujeme. |
Nezabudnime skontrolovať, kedy sa zatvorí výstupný kanál, ktorý prechádzame vo funkcii To sa stane po dobehnutí všetkých robotníckych gorutín, čo znamená koniec vstupných dát a teda koniec výsledkov. |
Recommend
-
14
Scala 3 Kan Extensions Scala 3 Kan Extensions Table of Contents 可以跑的源码在这里 👉 https://github.com/jcouyang/meow 什么是 看展Kan Extensions? 可...
-
5
Books that changed my lifeI spent my whole life running from negative emotions – I was very conflict avoidant. It takes real courage to say how you feel in the moment, and inspiring others to reciprocate. Being able to wholly feel...
-
5
Otvorila monádu a ... našla v nej celý výpočet! /home/robonovotny Otvorila monádu a … našla v nej celý výpočet! 2021/09/26
-
3
優化重構 Worker Pool 程式碼 Posted on June 7, 2022 | 3 minutes | 557 words | Appleboy
-
12
Scala 3 Kan Extensions Scala 3 Kan Extensions Table of Contents 可以跑的源码在这里 👉
-
5
Čo je gorutina? Gorutina je ľahučké vlákenko na vykonávanie paralelných úloh v Go. Spustime desaťtisíc gorutín, ktoré si sekundu pospia a potom vypíšu bodku. ...
-
2
Gorutiny a atomické počítadlá 2023/01/06 Počítajme slová vo vetách s gorutinami! Chalupkov fragment najprv rozbijeme na riadky. Každý z nich pošleme do
-
2
Tisíc zlatých, tisíc zlatých gorutín V minulom dieli sme spúšťali jedinú gorutinu, ale je čas pridať plyn. Spustime tisíc gorutín, ktoré si sekundu...
-
12
那是什么样的旅途呢那是什么样的旅途...
-
4
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK