2009-11-15 13 views
3

我刚才才知道Google的编程语言Go。我一直对它提供的并发支持很感兴趣,并着手对它进行更多的了解。但是,我想了解Go是如何实现并发性的一个特性,到目前为止我还没有看到任何证据表明这个特性完全存在。是否有可能从Go中的一些goroutines中收到结果?

下面是一个假设情况:假设我们正在编写一个函数来确定特定输入的Foo值。对于任何给定的输入,Foo值可以在域A或域B中找到(不在两者中)。在这些领域进行搜索的技术是完全不同的,但他们共享成功的搜索往往会很快返回的属性,而不成功的搜索必须经过整个数据集才能详尽无遗,因此需要很长时间。

现在,在采用并发的其他语言(如Cilk)中,可以编写函数Foosearch,以便生成一个Asearch函数和一个Bsearch函数。这些函数可以同时运行,并且每当或者都得出答案时,该答案将被报告给调用函数Foosearch,该函数将终止它所产生的没有返回的任何函数。

然而,使用Go的goroutines,看起来您只能将两个例程与一个频道连接 - 因此您无法设置Asearch或Bsearch可以发送的频道,具体取决于哪个频道首先找到答案,以及有Foosearch从它读取。它也看起来像你不能从一个渠道读取没有阻止它 - 所以你不能让Foosearch启动Asearch和Bsearch,并从两个渠道建立渠道,然后运行在一个循环检查,看看是否有一个产生一个答案。

我对Go的并发性限制的理解是否正确?是否有另一种方法来实现给定的结果?

回答

16

不,我不相信你的围棋极限的理解是正确的。

首先,我在Go中看到的任何东西都限制了两个例程之间的通信。您可以将相同的频道传递给Asearch和Bsearch,然后无论哪个人都可以在该频道上发送结果。

如果您想要使用两个通道,并等待其中一个获取结果,则可以使用select语句。从Go tutorial,示例选择信道所使用的发送请求,和一个用于用信号通知所述服务器退出:

21 func server(op binOp, service chan *request, quit chan bool) { 
22  for { 
23   select { 
24   case req := <-service: 
25    go run(op, req); // don't wait for it 
26   case <-quit: 
27    return; 
28   } 
29  } 
30 } 

此外,虽然从一个信道接收正常块,也可以从一个做一个non-blocking receive渠道。

如果接收表达在 形式

x, ok = <-ch 
x, ok := <-ch 
var x, ok = <-ch 

接收操作变得 无阻塞的 分配或初始化被使用。如果操作可以继续,则布尔变量ok将 设置为true,并将值存储在 x;如果操作可以继续执行,则布尔变量ok将 设置为true,并将值存储在 x;否则ok设置为false,并且对于其类型为 (§The zero value)的x 设置为零值。

因此,有几种方法可以等待多个goroutine的结果而不会阻塞。我想我会用多个通道使用select进行多路复用,这样你就可以轻松地知道哪个例程返回了结果,而不必将该信息打包为您发送的值或进行其他形式的带外通信。

5

您可以使用select关键字从多个渠道接收。

该值将从其他结果早于结果的频道获取。

var c1, c2 chan int; 
var result int; 

select { 
case result = <-c1: 
    print("received ", result, " from c1\n"); 
case result = <-c2: 
    print("received ", result, " from c2\n"); 
} 

Reference

相关问题