質問編集履歴

3 修正

puroko3

puroko3 score 159

2018/07/17 21:22  投稿

チャネルで理解出来ない挙動があるので解説お願いしたいです。
```Go
package main
import (
 "fmt"
 "math/rand"
 "time"
)
const goroutines = 10
const maxProcesses = 3
func main() {
 //3つまでint型を受け取れるチャネル
 semaphore := make(chan int, maxProcesses)
 //10つまでint型を受け取れるチャネル
 notify := make(chan int, goroutines)
 for i := 0; i < goroutines; i++ {
   fmt.Println(i, "i")
   go func(no int, semaphore chan int, notify chan<- int) {
     //semaphoreに0を送信
     semaphore <- 0
     //ランダムな秒数で処理を一時停止させる
     time.Sleep(time.Duration(rand.Int63n(3)) * time.Second)
     //semaphoreに送信された値を取り出してバッファを解放する。解放しなかれば3回ループした時点で止まる。
     fmt.Println(<-semaphore, "semaphore受信")
     //notifyに引数のnoを送信する
     notify <- no
   }(i, semaphore, notify)
 }
 for i := 0; i < goroutines; i++ {
   //notifyに送信された値を全て取り出す。同期の意味合いも持つ
   fmt.Println(<-notify, "notify受信")
 }
 fmt.Println("全て完了")
}
```
基礎からわかるGo言語という書籍のサンプルコードを少し変形させて、自分なりの理解をコメントにしました。
もし理解に誤りがあるようなら指摘してくださると嬉しいです。
本題に入りまして、今つまづいているのはsemaphoreの部分です。
このコードを実行させると大体の場合、forのiの0から3以上が表示されて、
その後、semaphoreの受信が表示されるのですが、その前にsemaphore <- 0の部分が3つまでしか受け取れないのでエラーが起きてしまうように感じます。
<- semaphoreでバッファの解放?を行っているみたいですが、先にiが3以上まで表示されるという事は、解放する前に受け取っているという事なので、エラーが起きないのが何故なのか理解出来てない状況です...
わかるかたいらしたらお願いします
エラーメッセージ
fmt.Println(<-semaphore, "semaphore受信")
の部分をコメントアウトした時のエラーメッセージ
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
   C:/Go/src/mytest/test1.go:33 +0x18b
goroutine 5 [chan send]:
main.main.func1(0x0, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 6 [chan send]:
main.main.func1(0x1, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 7 [chan send]:
main.main.func1(0x2, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 10 [chan send]:
main.main.func1(0x5, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 11 [chan send]:
main.main.func1(0x6, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 12 [chan send]:
main.main.func1(0x7, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 13 [chan send]:
main.main.func1(0x8, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
exit status 2
  • Go

    649 questions

    Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

2 エラースタックトレースの追記

puroko3

puroko3 score 159

2018/07/17 20:30  投稿

チャネルで理解出来ない挙動があるので解説お願いしたいです。
```Go
package main
import (
 "fmt"
 "math/rand"
 "time"
)
const goroutines = 10
const maxProcesses = 3
func main() {
 //3つまでint型を受け取れるチャネル
 semaphore := make(chan int, maxProcesses)
 //10つまでint型を受け取れるチャネル
 notify := make(chan int, goroutines)
 for i := 0; i < goroutines; i++ {
   fmt.Println(i, "i")
   go func(no int, semaphore chan int, notify chan<- int) {
     //semaphoreに0を送信
     semaphore <- 0
     //ランダムな秒数で処理を一時停止させる
     time.Sleep(time.Duration(rand.Int63n(3)) * time.Second)
     //semaphoreに送信された値を取り出してバッファを解放する。解放しなかれば3回ループした時点で止まる。
     fmt.Println(<-semaphore, "semaphore受信")
     //notifyに引数のnoを送信する
     notify <- no
   }(i, semaphore, notify)
 }
 for i := 0; i < goroutines; i++ {
   //notifyに送信された値を全て取り出す。同期の意味合いも持つ
   fmt.Println(<-notify, "notify受信")
 }
 fmt.Println("全て完了")
}
```
基礎からわかるGo言語という書籍のサンプルコードを少し変形させて、自分なりの理解をコメントにしました。
もし理解に誤りがあるようなら指摘してくださると嬉しいです。
本題に入りまして、今つまづいているのはsemaphoreの部分です。
このコードを実行させると大体の場合、forのiの0から3以上が表示されて、
その後、semaphoreの受信が表示されるのですが、その前にsemaphore <- 0の部分が3つまでしか受け取れないのでエラーが起きてしまうように感じます。
<- semaphoreでバッファの解放?を行っているみたいですが、先にiが3以上まで表示されるという事は、解放する前に受け取っているという事なので、エラーが起きないのが何故なのか理解出来てない状況です...
わかるかたいらしたらお願いします。
わかるかたいらしたらお願いします
エラーメッセージ
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
   C:/Go/src/mytest/test1.go:33 +0x18b
goroutine 5 [chan send]:
main.main.func1(0x0, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 6 [chan send]:
main.main.func1(0x1, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 7 [chan send]:
main.main.func1(0x2, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 10 [chan send]:
main.main.func1(0x5, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 11 [chan send]:
main.main.func1(0x6, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 12 [chan send]:
main.main.func1(0x7, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
goroutine 13 [chan send]:
main.main.func1(0x8, 0xc04206a080, 0xc042076000)
   C:/Go/src/mytest/test1.go:22 +0x3e
created by main.main
   C:/Go/src/mytest/test1.go:20 +0x14b
exit status 2
  • Go

    649 questions

    Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

1 受信する部分が送信になっていたので修正

puroko3

puroko3 score 159

2018/07/17 00:20  投稿

チャネルで理解出来ない挙動があるので解説お願いしたいです。
```Go
package main
import (
 "fmt"
 "math/rand"
 "time"
)
const goroutines = 10
const maxProcesses = 3
func main() {
 //3つまでint型を受け取れるチャネル
 semaphore := make(chan int, maxProcesses)
 //10つまでint型を受け取れるチャネル
 notify := make(chan int, goroutines)
 for i := 0; i < goroutines; i++ {
   fmt.Println(i, "i")
   go func(no int, semaphore chan int, notify chan<- int) {
     //semaphoreに0を送信
     semaphore <- 0
     //ランダムな秒数で処理を一時停止させる
     time.Sleep(time.Duration(rand.Int63n(3)) * time.Second)
     //semaphoreに送信された値を取り出してバッファを解放する。解放しなかれば3回ループした時点で止まる。
     fmt.Println(<-semaphore, "semaphore信")
     fmt.Println(<-semaphore, "semaphore信")
     //notifyに引数のnoを送信する
     notify <- no
   }(i, semaphore, notify)
 }
 for i := 0; i < goroutines; i++ {
   //notifyに送信された値を全て取り出す。同期の意味合いも持つ
   fmt.Println(<-notify, "notify信")
   fmt.Println(<-notify, "notify信")
 }
 fmt.Println("全て完了")
}
```
基礎からわかるGo言語という書籍のサンプルコードを少し変形させて、自分なりの理解をコメントにしました。
もし理解に誤りがあるようなら指摘してくださると嬉しいです。
本題に入りまして、今つまづいているのはsemaphoreの部分です。
このコードを実行させると大体の場合、forのiの0から3以上が表示されて、
その後、semaphoreの信が表示されるのですが、その前にsemaphore <- 0の部分が3つまでしか受け取れないのでエラーが起きてしまうように感じます。
その後、semaphoreの信が表示されるのですが、その前にsemaphore <- 0の部分が3つまでしか受け取れないのでエラーが起きてしまうように感じます。
<- semaphoreでバッファの解放?を行っているみたいですが、先にiが3以上まで表示されるという事は、解放する前に受け取っているという事なので、エラーが起きないのが何故なのか理解出来てない状況です...
わかるかたいらしたらお願いします。
  • Go

    649 questions

    Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る