我是这门语言的新手,所以请耐心等待。
我很好奇 GO 如何处理线程可用的数据存储,因为非局部变量也可以是非易失性的,例如在 Java 中。
GO有通道的概念,从本质上讲——线程间通信,意味着它绕过处理器缓存,直接读/写到堆。
此外,在 go lang 文档中没有找到对 volatile 的任何引用。
我是这门语言的新手,所以请耐心等待。
我很好奇 GO 如何处理线程可用的数据存储,因为非局部变量也可以是非易失性的,例如在 Java 中。
GO有通道的概念,从本质上讲——线程间通信,意味着它绕过处理器缓存,直接读/写到堆。
此外,在 go lang 文档中没有找到对 volatile 的任何引用。
TL;DR : Go 没有一个关键字来使多个 goroutine 可以安全地写入/读取变量。为此使用该sync/atomic
软件包。或者更好的是不要通过共享内存进行通信;相反,通过通信共享内存。
Go Memory Model的一些摘录。
如果一个 goroutine 的效果必须被另一个 goroutine 观察到,可以使用锁或通道通信等同步机制来建立相对顺序。
错误同步部分的示例之一是忙于等待值的示例。
更糟糕的是,由于两个线程之间没有同步事件,因此无法保证 main 会观察到对 done 的写入。main 中的循环不能保证完成。
事实上,这段代码(play.golang.org/p/K8ndH7DUzq)永远不会退出。
Go 的内存模型没有提供解决非标准内存的方法。如果您对设备的 I/O 总线具有原始访问权限,则需要使用汇编或 C 将值安全地写入内存位置。我只需要在通常排除使用 Go 的设备驱动程序中执行此操作。
简单的答案是当前的 Go 规范不支持 volatile。
如果您确实有需要 volatile 的用例之一,例如标准库中现有 包不支持的低级原子内存访问,或者对硬件映射内存的无缓冲访问,则需要在 C 中链接或汇编文件。
请注意,如果您确实使用 GC 编译器套件所理解的 C 或程序集,那么您甚至不需要 cgo,因为 [568]c C/asm 编译器也能够处理它。
您可以在 Go 的源代码中找到相关示例。例如:
Grep 用于许多其他实例。
关于 Go 中的内存访问是如何工作的,请查看 Go 内存模型。
不,go 不支持 volatile 或 register 语句。
有关更多信息,请参阅此帖子。Go for C++ 程序员指南中也提到了这一点。
Go 内存模型文档解释了为什么“易失性”的概念在Go 中没有应用。
松散地:除其他外,goroutine 可以自由地将 goroutine-local 更改缓存在寄存器中,因此其他 goroutine 无法观察到这些更改。要将这些更改“刷新”到内存,必须执行同步。通过使用锁或通过通信(通道发送或接收)。