当前位置:  开发笔记 > 编程语言 > 正文

Go中的多线程.有人可以向我解释这些答案吗?

如何解决《Go中的多线程.有人可以向我解释这些答案吗?》经验,为你挑选了1个好方法。

我在模拟考试中得到了两个问题.我得到了答案,但无法弄清楚背后的理由.

我将首先发布代码,然后发布问题和答案.也许有人会这么好解释我的答案?

package main

import "fmt"

func fact(n int, c chan int, d chan int) {

    k := /* code to compute factorial of n */

    z := <- d

    c <- k + z

    d <- z + 1

}

func main() {

    r := 0

    c := make(chan int)
    d := make(chan int)

    for i = 0 ; i < N ; i++ {
        go fact(i,c,d)
    }

    d <- 0

    for j = 0 ; j < N ; j++ {
        r = r + <-c
    }

    fmt.Printf("result = %d\n",r)

}

第一个问题是:

如果在主程序中省略"d < - 0"行,程序如何表现,为什么?

老师的答案是:

所有线程的状态都被阻塞,也是主线程.

第二个问题是:

如果我们交换事实程序的前两行,整个计划的效率会如何影响?

答案是:

所有线程都将按顺序运行.每个线程只有在完成时才会触发另一个线程.



1> Rob Napier..:

最好不要将其视为"多线程".Go为并发提供直接设施,而不是线程.它恰好通过线程实现其并发性,但这是一个实现细节.请参阅Rob Pike的演讲,对于更深入的讨论,并发不是并行性.

您的问题的关键是默认情况下通道是同步的(如果它们在构造期间没有被缓冲).当一个goroutine写入一个通道时,它将阻塞,直到某个其他goroutine从该通道读取.这条线执行时:

z := <- d

在此行执行之前无法继续:

d <- 0

如果d频道上没有可用的值,fact将永远不会继续.这对你来说很明显.但反过来也是如此.直到某些东西从d频道读取,主要的goroutine无法继续.通过这种方式,无缓冲通道可在并发goroutine之间提供同步点.

同样,在出现某个值之前,主循环无法继续c.我发现使用两个手指并指向每个goroutine中的当前代码行很有用.前进一根手指直到进入通道操作.然后前进另一个直到它到达通道操作.如果您的手指指向同一频道上的读取和写入,则您可以继续.如果他们不是,那么你就陷入僵局.

如果你认为这一点,你会发现一个问题.这个程序泄漏了goroutine.

func fact(n int, c chan int, d chan int) {
    k := /* code to compute factorial of n */
    z := <- d // (1)
    c <- k + z
    d <- z + 1 // (2)
}

在(2)我们试着写d.什么将允许继续?另一个goroutine阅读d.记住,我们开始使用Ngoroutines,并且所有人都试图阅读d.只有其中一个会成功.其他人将阻止(1),等待出现的东西d.当第一个到达(2)时会发生这种情况.然后那个goroutine退出,随机goroutine将继续.

但是会有一个永远无法写入的最终goroutine,d它会泄漏.为了解决这个问题,需要在最终决定之前添加以下内容Printf:

<-d

这将允许最后一个goroutine退出.

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有