Nechápem tuto Go rutinu

Nechápem tuto Go rutinu
« kdy: 20. 08. 2019, 11:06:51 »
Mam tento priklad:

Kód: [Vybrat]
package main

import (
    "fmt"
    "time"
)

func greet(c chan string) {

    println("blocking")

    val, ok := <- c

    println(val)
    println(ok)

    println("waiting")

    val2, ok2 := <- c

    println(val2)
    println(ok2)

    println("ending")
}

func main() {
    c := make(chan string)

    go greet(c)

    time.Sleep(5000 * time.Millisecond)

    c <- "John"
    c <- "Jim"
}

vystup je

Kód: [Vybrat]
blocking
John
true
waiting
Jim
true
ending

Takze sa spusti go rutina greet(), prvy <- c je blokujuci, poslem c <- John, odblokuje sa to a vypise, poslem druhy krat c <- Jim, odblokuje sa to tiez a skonci sa program.

Problem je, ze bez toho time.Sleep(5000 * time.Millisecond) po go greet(c) sa vypise len John ale nie Jim.

Preco to tak je?

Ved greet ma v sebe dva blokujuce <- c, preco ked tam nedam ten time.Sleep, tak to vypise len John-a a skonci sa program a Jim sa akokeby odignoruje?
« Poslední změna: 20. 08. 2019, 13:00:24 od Petr Krčmář »


Re:nechapem tuto go rutinu
« Odpověď #1 kdy: 20. 08. 2019, 11:15:36 »
Tak odpoved je, ze ten channel mam unbuffered, takze cokolvek tam poslem cez c <- tak to nebude cakat, kym to niekto precita, takze sa stihne poslat John, to sa vypise, posle sa Jim a program skonci bez toho aby to doplavalo k druhemu <- c v greet.

Ked deklarujem channel s kapacitou 1, tak to vypise aj bez sleepu.

Na druhej strane ale nechapem, co s tym ma ten sleep spolocny, ze to zrazu vypise spravne, ked je ten channel unbuffered.

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:nechapem tuto go rutinu
« Odpověď #2 kdy: 20. 08. 2019, 12:17:44 »
Tak odpoved je, ze ten channel mam unbuffered, takze cokolvek tam poslem cez c <- tak to nebude cakat, kym to niekto precita, takze sa stihne poslat John, to sa vypise, posle sa Jim a program skonci bez toho aby to doplavalo k druhemu <- c v greet.

Ked deklarujem channel s kapacitou 1, tak to vypise aj bez sleepu.

Na druhej strane ale nechapem, co s tym ma ten sleep spolocny, ze to zrazu vypise spravne, ked je ten channel unbuffered.
Unbuffered naopak čeká.

Re:Nechápem tuto Go rutinu
« Odpověď #3 kdy: 20. 08. 2019, 13:09:53 »
Tak v první řadě si musíš ujasnit, že program nečeká na ukončení všech gorutin - zkus si to:
https://play.golang.org/p/EWb7EBbneQk

Čili za druhé: tvoje otázka "proč mi to (ne)vypsalo?" by vůbec neměla být zkoumána, protože pokud na dokončení gorutiny explicitně nepočkáš, pak je chování programu náhodné (nedefinované). Může něco vypsat a nemusí z definice. Vůbec nezkoumej, kdy ano a kdy ne. Pokud chceš na dokončení gorutiny počkat, udělej to (viz např. https://stackoverflow.com/a/32383393). Pokud čekat nechceš, očekávej libovolný výsledek.

P.S. hodnoty z channelu se typicky zpracovávají pomocí range. Jiné řešení dává smysl málo kdy.

Re:Nechápem tuto Go rutinu
« Odpověď #4 kdy: 21. 08. 2019, 13:52:02 »
Tak v první řadě si musíš ujasnit, že program nečeká na ukončení všech gorutin - zkus si to:
https://play.golang.org/p/EWb7EBbneQk

na tyhle experimenty se hodí https://golang.org/pkg/runtime/#Goexit
https://play.golang.org/p/sEefsqrZNPR


Re:Nechápem tuto Go rutinu
« Odpověď #5 kdy: 21. 08. 2019, 14:55:40 »

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Nechápem tuto Go rutinu
« Odpověď #6 kdy: 21. 08. 2019, 17:50:27 »
Tak v první řadě si musíš ujasnit, že program nečeká na ukončení všech gorutin - zkus si to:
https://play.golang.org/p/EWb7EBbneQk

na tyhle experimenty se hodí https://golang.org/pkg/runtime/#Goexit
https://play.golang.org/p/sEefsqrZNPR
Akorát zrovna na hlavním vlákně dělá Goexit neplechu.

Re:Nechápem tuto Go rutinu
« Odpověď #7 kdy: 21. 08. 2019, 17:51:40 »
Akorát zrovna na hlavním vlákně dělá Goexit neplechu.
Jakou?

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Nechápem tuto Go rutinu
« Odpověď #8 kdy: 21. 08. 2019, 17:59:59 »
Akorát zrovna na hlavním vlákně dělá Goexit neplechu.
Jakou?
Viz dokumentace z odkazu výše. (“If all other goroutines exit, the program crashes.”)

Re:Nechápem tuto Go rutinu
« Odpověď #9 kdy: 21. 08. 2019, 18:03:14 »
Viz dokumentace z odkazu výše. (“If all other goroutines exit, the program crashes.”)
To jsem pochopil jako "zamer ne neplechu" ("feature not a bug" ;) ).

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Nechápem tuto Go rutinu
« Odpověď #10 kdy: 21. 08. 2019, 18:31:31 »
Viz dokumentace z odkazu výše. (“If all other goroutines exit, the program crashes.”)
To jsem pochopil jako "zamer ne neplechu" ("feature not a bug" ;) ).
Aha. Na mě to působí jako vedlejší efekt toho, když to někdo zavolá na hlavním vlákně. Ale pro experimenty asi dobrý, disk to nejspíš nemaže...

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Nechápem tuto Go rutinu
« Odpověď #11 kdy: 21. 08. 2019, 18:32:27 »
Viz dokumentace z odkazu výše. (“If all other goroutines exit, the program crashes.”)
To jsem pochopil jako "zamer ne neplechu" ("feature not a bug" ;) ).
BTW jak jde učení závislostních typů?

Re:Nechápem tuto Go rutinu
« Odpověď #12 kdy: 21. 08. 2019, 18:41:46 »
Aha. Na mě to působí jako vedlejší efekt toho, když to někdo zavolá na hlavním vlákně. Ale pro experimenty asi dobrý, disk to nejspíš nemaže...
Ja kdyz jsem to cetl, tak mi blesklo hlavou, ze to nejspis bude proto, ze by se nevedelo, jakej se ma z programu vratit navratovej kod. Ale to bude asi spis blbost :)

BTW jak jde učení závislostních typů?
Precetl jsem asi padesat stranek a pak jsem to musel odlozit kvuli jinym povinnostem a obavam se, ze az se k tomu vratim, tak budu muset zacit zas od zacatku, pac mezi tim detaily zapomenu :)

Ta knizka je stylove teda hodne zajimava :) ale nemuzu rict, ze by mi to uplne skvele vyhovovalo. Je to trosku moc rozvlacny na muj vkus. Uprednostnil bych o malicko min taskaric a vic vyklad k veci. Idealni mi prijde uroven taskaric, kterou ma Learn You Some (Erlang|Haskell) for Great Good!

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Nechápem tuto Go rutinu
« Odpověď #13 kdy: 21. 08. 2019, 18:43:49 »
Aha. Na mě to působí jako vedlejší efekt toho, když to někdo zavolá na hlavním vlákně. Ale pro experimenty asi dobrý, disk to nejspíš nemaže...
Ja kdyz jsem to cetl, tak mi blesklo hlavou, ze to nejspis bude proto, ze by se nevedelo, jakej se ma z programu vratit navratovej kod. Ale to bude asi spis blbost :)
Podle mě to je fakt jen vedlejší efekt, scheduleru prostě dojdou korutiny, což vyhodnotí jako deadlock a chcípne.

Re:Nechápem tuto Go rutinu
« Odpověď #14 kdy: 21. 08. 2019, 18:45:23 »
Podle mě to je fakt jen vedlejší efekt, scheduleru prostě dojdou korutiny, což vyhodnotí jako deadlock a chcípne.
Asi mas pravdu. Ale kdyby chteli, tak by scheduler v tehle situaci klidne mohl udelat exit(0), ze :)