dtj88302 2014-07-23 09:19
浏览 42
已采纳

为什么在这里发生僵局

I am trying to understand, how golang channel works. I read a book about the go language and found the following example.

package main

import (
    "fmt"
)

// Send the sequence 2, 3, 4, ... to returned channel 
func generate() chan int {
    ch := make(chan int)
    go func() {
        for i := 2; i <= 100 ; i++ {
            ch <- i
        }
    }()
    return ch
}

// Filter out input values divisible by 'prime', send rest to returned channel
func filter(in chan int, prime int) chan int {
    out := make(chan int)
    go func() {
        for {
            if i := <-in; i%prime != 0 {
                out <- i
            }
        }
    }()
    return out
}

func sieve() chan int {
    out := make(chan int)
    go func() {
        ch := generate()
        for {
            prime := <-ch
            ch = filter(ch, prime)
            out <- prime
        }
    }()
    return out
}

func main() {
    primes := sieve()
    for {
        fmt.Println(<-primes)
    }
}

When I run this programm, I've got a deadlock, but when I change the generate function to

// Send the sequence 2, 3, 4, ... to returned channel 
func generate() chan int {
    ch := make(chan int)
    go func() {
        for i := 2; ; i++ {
            ch <- i
        }
    }()
    return ch
}

Then the programm will run the infinite loop, but not deadlock. Why do I get deadlock, when I remove the condition in for loop?

  • 写回答

2条回答 默认 最新

  • dongyi9330 2014-07-23 10:35
    关注

    What do you mean with blocking principle?

    You can see it illustrated in the blog post "The Nature Of Channels In Go "

    for an unbuffered channel:

    http://3.bp.blogspot.com/-vnJIWvlbP-E/UwDVICJKB9I/AAAAAAAANX0/T04V_58i8Vs/s1600/Screen+Shot+2014-02-16+at+10.10.54+AM.png

    (Illustration from blog post "The Nature Of Channels In Go ", written by William Kennedy, Feb. 2014)

    Unbuffered channels have no capacity and therefore require both goroutines to be ready to make any exchange.
    When a goroutine attempts to write a resource to an unbuffered channel and there is no goroutine waiting to receive the resource, the channel will lock the goroutine and make it wait.
    When a goroutine attempts to read from an unbuffered channel, and there is no goroutine waiting to send a resource, the channel will lock the goroutine and make it wait.

    That is what happens in your case with your reader:

    func main() {
        primes := sieve()
        for {
            fmt.Println(<-primes)
        }
    }
    

    since primes is never closed, main remains blocked.
    It (main) is in step 3:

    in step 3, the goroutine on the right places his hand into the channel or performs a read.
    That goroutine is also locked in the channel until the exchange is complete.

    The sender never calls close(primes).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效