25

我是这门语言的新手,所以请耐心等待。

我很好奇 GO 如何处理线程可用的数据存储,因为非局部变量也可以是非易失性的,例如在 Java 中。

GO有通道的概念,从本质上讲——线程间通信,意味着它绕过处理器缓存,直接读/写到堆。

此外,在 go lang 文档中没有找到对 volatile 的任何引用。

4

4 回答 4

16

TL;DR : Go 没有一个关键字来使多个 goroutine 可以安全地写入/读取变量。为此使用该sync/atomic软件包。或者更好的是不要通过共享内存进行通信;相反,通过通信共享内存


两个意思的两个答案volatile 挥发性文图

.NET/Java并发

Go Memory Model的一些摘录。

如果一个 goroutine 的效果必须被另一个 goroutine 观察到,可以使用锁或通道通信等同步机制来建立相对顺序。

错误同步部分的示例之一是忙于等待值的示例。

更糟糕的是,由于两个线程之间没有同步事件,因此无法保证 main 会观察到对 done 的写入。main 中的循环不能保证完成。

事实上,这段代码(play.golang.org/p/K8ndH7DUzq)永远不会退出。

C/C++非标准内存

Go 的内存模型没有提供解决非标准内存的方法。如果您对设备的 I/O 总线具有原始访问权限,则需要使用汇编或 C 将值安全地写入内存位置。我只需要在通常排除使用 Go 的设备驱动程序中执行此操作。

于 2013-08-29T01:43:16.997 回答
5

简单的答案是当前的 Go 规范不支持 volatile。

如果您确实有需要 volatile 的用例之一,例如标准库中现有 不支持的低级原子内存访问,或者对硬件映射内存的无缓冲访问,则需要在 C 中链接或汇编文件。

请注意,如果您确实使用 GC 编译器套件所理解的 C 或程序集,那么您甚至不需要 cgo,因为 [568]c C/asm 编译器也能够处理它。

您可以在 Go 的源代码中找到相关示例。例如:

Grep 用于许多其他实例。

关于 Go 中的内存访问是如何工作的,请查看 Go 内存模型

于 2013-08-28T15:58:06.400 回答
3

不,go 不支持 volatile 或 register 语句。

有关更多信息,请参阅此帖子Go for C++ 程序员指南中也提到了这一点。

于 2013-08-28T14:46:15.123 回答
3

Go 内存模型文档解释了为什么“易失性”的概念在Go 中没有应用。

松散地:除其他外,goroutine 可以自由地将 goroutine-local 更改缓存在寄存器中,因此其他 goroutine 无法观察到这些更改。要将这些更改“刷新”到内存,必须执行同步。通过使用锁或通过通信(通道发送或接收)。

于 2013-08-28T14:50:49.440 回答