Go: Channels nebo Mutexes?

Go má skvělou podporu pro concurrency. Jedná se o gorutiny. Ty vám umožňuje spouštět paralelně v rámci aplikace různé subtasky. A narozdíl od NodeJS se nejedná o singlethread aplikaci, kde všechen asynchronní kód vám běží v rámci jednoho threadu, ale v případě Go se jedná o opravdu multithread aplikaci, která dokáže rozhýbat všechny jádra vašeho procesoru.

Abych byl přesnější, jedná se green threads a Go scheduler implementuje cooperative multitasking, což je leší než preemtivní multitasking.

A ještě upřesnění k NodeJS: i ten už nějakou dobu umí pracovat s thready skrze workery, ale není to taková paráda jako v Go. Nicméně nějak to jde, psal jsem o tom tady. Pokud byste ale s thready pracovat v NodeJS, museli byste významně překopat architektůru své aplikace na více méně nezávislé JS bloky, miniaplikace, které byste pak dokázali spouštět, forkovat, na více jádrech. Dobré je, že workeři si umí posílat zprávy, sdílet paměť a tam mezi sebou komunikovat.

Nicméně byť implementace v NodeJS je, efektivita není zdaleka taková jako v Go. Runtime Go s gorutinami počíta a skrze své interní struktůry je velice hezky a efektivně realokuje na fyzické thready procesoru. Radost pohledět.

Tak teď k tem kanálům a mutexům

Pokud se tedy rozhodnote svůj kód napsat tak, aby opravdu běžel ve více vláknech, budete potřebovat synchronizovat jednotlivé gorutiny v rámci aplikace. A to je vždy ten největší opruz. Ale ne v Go. Ten nabízí interní mechanizky pomocí kterých tohoto dosáhnete. Jedná se o channels a mutexes.

Pomocí obou se dá dosáhnout synchronizace prováděných nezávislých operací nad nějakou datovou bázi se sdílenou logikou.

Na něco mohou být vhodné channles, někde se více budou hodit mutexes. Příjde na to.

A jak poznat kdy co použít. V každém případě je jen na vás, jak si to napíšete, ale jako vodítko můžete použít následující algoritmus:

if performance_critical {
    return MUTEXES
}

if transfering_data_ownership {
    return CHANNELS
}

if guarding_internal_state_of_struct {
    return MUTEXES
}

if coordinating_multiple_pieces_of_logic {
    return CHANNELS
}

return MUTEXES

Obecně by se dalo říct

Pokud máte logiku sdílení postavenou jako flow, pak se vám budou hodit cannels. Jinak jsou mutexes to pravé ořechové.