Structの中にあるチャンネルに値をsendするとdeadlockする

投稿者: Anonymous

Golangで下記のコードを実行するとdeadlockを起こします。
SetValueの中で、引数として与えられたvalueg.CHに渡す時にdeadlockになっているようです。
なぜ、deadlockになってしまうのでしょうか?


package main

import (
    "fmt"
)

type GeneratorChannel struct {
    X  int
    CH chan int
}

func New() *GeneratorChannel {
    s := GeneratorChannel{}
    s.CH = make(chan int)
    return &s
}

func (g *GeneratorChannel) SetValue(value int) {
    g.X = value
    g.CH <- g.X

}
func (g *GeneratorChannel) GetChannelValue() int {
    return <-g.CH
}

func main() {
    g := New()
    g.SetValue(4)
    fmt.Println(g.GetChannelValue())

}



解決

s.CH = make(chan int)

バッファなしチャネル(容量0)として作成しているため、送信操作g.CH <- g.Xがブロッキングしています。このとき同時に受信操作return <-g.CHが行われれば、送受信が成立してブロッキング解除されますが、掲示コードでは送受信を同じGoroutineで行おうとしているため、永遠に受信が完了せずデッドロックしています。

解決策1: チャネルの容量を1以上に設定する。送信された値は一旦バッファリングされ、後続の受信操作にて値が取り出されます。いずれの操作もブロッキングしないため、デッドロックは回避されます。

s.CH = make(chan int, 1)

ただしこの方法では、チャネルのバッファがあふれると再びデッドロックします。チャネル容量が1の場合、2つの値を連続送信するとデッドロックします。

解決策2: 送信操作を受信とは異なるGoroutine上で実行する。異なるGoroutine間でのチャネル通信となり、デッドロックが回避されます。(チャネルは本来Goroutine間の同期通信に用いる仕組みですから、こちらの方が正攻法かと思います。)

go g.SetValue(4)
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *