Golang、App Engine、通道和线程安全

Posted

技术标签:

【中文标题】Golang、App Engine、通道和线程安全【英文标题】:Golang, App Engine, Channels and Thread Safety 【发布时间】:2014-10-30 09:27:23 【问题描述】:

http://blog.golang.org/go-and-google-app-engine

“此外,尽管存在 goroutine 和通道,但当 Go 应用在 App Engine 上运行时,在给定实例中仅运行一个线程。也就是说,所有 goroutine 在单个操作系统线程中运行,因此没有 CPU 并行性可用于给定的客户请求。我们预计此限制将在某个时候解除”

那是在 2011 年 5 月。它仍然是真的吗?

我有一个应用程序,它除了利用 Golang 的速度之外什么都不做;获取一些输入数据,对其执行内存计算,然后返回结果。从不接触数据存储区或任何其他 App Engine API。

我需要应用程序执行许多计算,最好是具有一定程度的并行化。因为我是一个 Golang 菜鸟,所以我只是编写了算法,没有考虑线程安全。当我一次发送一个请求时效果很好,但是当我尝试并行发送多个计算时,所有结果都是错误的。我怀疑,但不是 100% 知道,线程安全是问题所在,尤其是算法使用地图,而地图不是线程安全的

http://golang.org/doc/faq#atomic_maps

所以。如何使我的算法线程安全并获得一定程度的并行性。

首先想到的是使用通道,这似乎是线程安全的:

Is it possible to use Go's buffered channel as a thread-safe queue?

但后来我发现顶部的链接表明频道可能不可用。

所以..如果它们不可用,也许我需要为计算设置一个任务队列,一次只能执行一个计算。

有人能告诉我在 Golang App Engine 上实现一定程度的线程安全并行化的最佳模式吗?

谢谢。

【问题讨论】:

不知道是不是这个,但是任何全局变量仍然可以被多个 goroutine 更新,即使 GOMAXPROCS=1。如果你真的不需要全局变量来协调多个任务,那就让它们不再是全局的——也许将它们移动到你为每个请求分配的结构中。这个问题是一个非常笼统的描述,所以很难说更多。 【参考方案1】:

Google Appengine 目前只允许一个操作系统线程。

了解操作系统线程如何; Goroutines 及其堆栈;和调度器工作,我建议阅读the Scalable Go Scheduler proposal 或Analysis of the Go Runtime Scheduler。

由于您可以在单个线程上拥有多个通道、goroutines,因此 Appengine 可以很好地处理并发。如果您需要并行性(即不仅运行多个 goroutine,而且在多个处理器上运行它们),那么 Appengine 目前不是解决方案,因为它的 GOMAXPROCS 设置为 1。

就您的特定代码而言,您没有提供任何我们可以查看并帮助调试您的竞争条件的代码。如果您自己这样做,您将受益于阅读这篇关于the Go Race Detector的博客文章并使用the Go Race Detector

【讨论】:

【参考方案2】:

我不知道应用引擎目前是否支持多个操作系统线程,但即使只有一个操作系统级线程可用,您也绝对可以使用通道。您提供的链接确实声明“goroutines 和 channels are present”,它们都在一个操作系统级线程中处理。

【讨论】:

以上是关于Golang、App Engine、通道和线程安全的主要内容,如果未能解决你的问题,请参考以下文章

Golang✔️走进 Go 语言✔️ 第十六课 协程 & 通道

Golang✔️走进 Go 语言✔️ 第十六课 协程 & 通道

Golang通道

golang Goroutine安全模式使用通道来抽象使用频道。

golang协程——通道channel阻塞

Google App Engine Golang 连接到 Cloud SQL Postgres unix dial no such file or directory