9章 ゴルーチンとスレッド

9.8 ゴルーチンとスレッド

練習問題9.5

2つのバッファなしチャネルを介して卓球のようにメッセージを送り合う2つのゴルーチンを持つプログラム。
という問題です。

これですら難しく感じます。
ぱっと自分で思いついた方法は、まずいのだろうと思いますが、やってみました。

func pingpong(out, in, res chan int, timeout <-chan time.Time) {
    count := 0
    for {
        select {
        case <-timeout:
            res <- count
            fmt.Println("*** return pingpong")
            return
        case v := <-in:
            count = v + 1
            out <- count // (1)
        }
    }
}

この方法は(1)の部分で待たされてしまい、ゴルーチンのリークを起こしてしまうようです。
1秒間に170万回通信できているようです。

func pingpong(out, in, res chan int, timeout <-chan time.Time) {
    count := 0
    for {
        select {
        case <-timeout:
            res <- count
            fmt.Println("*** return pingpong")
            return
        case v := <-in:
            count = v + 1
        case out <- count:
        }
    }
}

この方法は、まともに動いているのか?と思いますが、1秒間47万回通信できている?ようです。

func pingpong(out, in, res chan int, timeout <-chan time.Time) {
    count := 0
    for {
        select {
        case <-timeout:
            res <- count
            fmt.Println("*** return pingpong")
            return
        case v := <-in:
            count = v + 1
            select {
            case out <- count:
            default:
            }
        }
    }
}

この方法はなんだか極端に遅く、1秒間に17回だけです。
(なにかおかしそうな気がしますが)

func pingpong(out, in, res chan int, timeout <-chan time.Time) {
    count := 0
    for {
        select {
        case <-timeout:
            res <- count
            fmt.Println("*** return pingpong")
            return
        case v := <-in:
            count = v + 1
            select {
            case <-timeout:
                res <- count
                fmt.Println("*** return pingpong")
                return
            case out <- count:
            }
        }
    }
}

これで、ゴルーチンリークを起こさず、1秒間に190万回通信できているみたいです。

なんだか方法が無数にあって難しく感じてしまい、まだ全く慣れてないなぁと思いました。