LoginSignup
4
4

More than 5 years have passed since last update.

golangでspawn, channel

Last updated at Posted at 2016-09-20

前の投稿では、Crystalをやってみる
http://qiita.com/tabetomo/items/754308a6cd48bcf56585
elixirでspawn, channel
http://qiita.com/tabetomo/items/ef3e822e907ae0a37614
と言って、Crystalとelixir上のspawn(軽量スレッド)で送受信する例をやってみました。このページでは同じことをgolangでやってみます。

以下は、crystalでのプログラム例と実行例。

spawn3.cr
ch1 = Channel(String).new(1)
ch2 = Channel(String).new(1)
done = Channel(Bool).new()

spawn do
  puts ch1.receive
  puts ch2.receive
  puts ch1.receive
  done.send(true) # end
end

spawn do
  ch1.send("apple")
  ch2.send("orange")
end
ch1.send("grape")

done.receive
terminal
$ crystall spawn3.cr                                                                  
grape                                                                                         
orange                                                                                        
apple 

golangでspawn(go func)

あまりにあっけなく同じものがgoでかけてしまいました。crystalで書いた時も思いましたが、あっさりしすぎ。

spawn3.go
package main
import "fmt"

func main() {
    ch1 := make(chan string, 1)
    ch2 := make(chan string, 1)
    done := make(chan bool, 0)
    go func() {
        msg := <-ch1
        fmt.Println(msg)
        msg = <-ch2
        fmt.Println(msg)
        msg = <-ch1
        fmt.Println(msg)
        done <- true
    }()
    go func() {
        ch1 <- "apple"
        ch2 <- "orange"
    }()
    ch1 <- "grape"
    <-done
}

実行例

terminal
$ go run spawn3.go                                                                   
grape                                                                                         
orange                                                                                        
apple 

備考;上記のプログラムですが、<-done (ここでは、doneチャネルで何かを受け取るまで待つ)で待ちを入れないと、grape を表示した時点でプログラムが終わってしまいます。

goでは、デッドロックするとエラー?

さて、最初crystalではサイズ0のチャネルでやっていました。

spawn3.cr
ch1 = Channel(String).new
ch2 = Channel(String).new

この場合、チャネルを受信するまで送信の先に処理が進みません(逆に言えば、受信されるまで送信側でブロックして待つことができます)。チャネルのサイズを0にしてしまうと、上記プログラムはgrapeを表示してデッドロックします(Ctrl-Cで止めるまで処理が戻ってきません)。

が、前の投稿のコメント欄ではgoでは、エラーになる、とご指摘をいただいていました。やってみようと思います。

spawn3.go
package main
import "fmt"

func main() {
    ch1 := make(chan string, 0)
    ch2 := make(chan string, 0)

普通にgoでもサイズ0でstringのチャネルは作成可能でした(ビルドもできて動作もします)。ここまでは問題ないです。が、

実行例

terminal
$ go build spawn3.go
$ ./spawn3                                                                          
grape                                                                                         
fatal error: all goroutines are asleep - deadlock!                                            

goroutine 1 [chan receive]:                                                                   
main.main()                                                                                   
        /Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:23 +0x143          

goroutine 5 [chan receive]:                                                                   
main.main.func1(0xc42001a0c0, 0xc42001a120, 0xc42001a180)                                     
        /Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:12 +0x145          
created by main.main                                                                          
        /Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:17 +0xbb           

goroutine 6 [chan send]:                                                                      
main.main.func2(0xc42001a0c0, 0xc42001a120)                                                   
        /Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:19 +0x5a           
created by main.main                                                                          
        /Users/xxx/proj/go/src/github.com/tabetomo/contest/spawn3.go:21 +0xe7 

のようにgoでは、grapeを表示した時点でデッドロックを検知(fatal error: all goroutines are asleep - deadlock!)して、実行時エラーになりました。これが良いのか悪いのかわかりませんが、all goroutines are asleepでは何もできない、ので、終わる方が良いのでしょう。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4