Go原子操作和内存顺序

huangapple go评论72阅读模式
英文:

Go atomic and memory order

问题

我正在将一个无锁队列从C++11移植到Go语言,并遇到了以下内容:

currentRead := atomic.LoadUint64(&q.writeIndex)

在移植后,我进行了基准测试,发现只使用LoadUint64似乎按预期工作,但速度慢了几个数量级。我想知道这些特殊操作对性能有多大影响。

在Go语言中,没有与C++中的这些操作完全等价的操作。Go语言的原子操作提供了一些基本的原子操作函数,如LoadUint64StoreUint64,但没有提供像C++中的memory_order_relaxedmemory_order_acquirememory_order_release这样的精确控制。

在Go语言中,原子操作的语义是强一致性的,即保证所有的内存访问都按照程序的顺序执行,不会发生重排序。这种强一致性的语义通常可以满足大多数情况下的需求。

如果你需要更细粒度的内存访问控制,可能需要使用其他的同步机制,如互斥锁或条件变量,来实现类似的功能。具体的实现方式取决于你的具体需求和代码结构。

英文:

I am porting a lock free queue from c++11 to go and i came across things such as

auto currentRead = writeIndex.load(std::memory_order_relaxed);

and in some cases std::memory_order_release and std::memory_order_aqcuire
also the equivelent for the above in c11 is something like

unsigned long currentRead = atomic_load_explicit(&q->writeIndex,memory_order_relaxed);

the meaning of those is described here

is there an equivalent to such thing in go or do i just use something like

var currentRead uint64 = atomic.LoadUint64(&q.writeIndex)

after porting i benchmarked and just using LoadUint64 it seems to work as expected but orders of magnitude slower and i wonder how much effect dose those specialized ops have on performance.

  • further info from the link i attached

> memory_order_relaxed:Relaxed operation: there are no synchronization
> or ordering constraints, only atomicity is required of this operation.
>
>
> memory_order_consume:A load operation with this memory order performs
> a consume operation on the affected memory location: no reads in the
> current thread dependent on the value currently loaded can be
> reordered before this load. This ensures that writes to data-dependent
> variables in other threads that release the same atomic variable are
> visible in the current thread. On most platforms, this affects
> compiler optimizations only.
>
> memory_order_acquire:A load operation with this memory order performs the acquire operation on the affected memory location: no
> memory accesses in the current thread can be reordered before this
> load. This ensures that all writes in other threads that release the
> same atomic variable are visible in the current thread.
>
>memory_order_release:A store operation with this memory order performs the release operation: no memory accesses in the current
> thread can be reordered after this store. This ensures that all writes
> in the current thread are visible in other threads that acquire or the
> same atomic variable and writes that carry a dependency into the
> atomic variable become visible in other threads that consume the same
> atomic.

答案1

得分: 7

你需要阅读《Go内存模型》(The Go Memory Model)。

你会发现,Go语言没有像C++那样的控制能力——在你的帖子中,并没有直接翻译C++的特性。这是Go语言作者的一个有意设计决策——Go的座右铭是“不通过共享内存来通信,而是通过通信来共享内存”。

假设标准的Go通道对你想要做的事情不够好,对于每个内存访问,你有两个选择:使用sync/atomic中的工具或不使用。你是否需要使用它们将取决于对Go内存模型的仔细阅读和对代码的分析,这只有你自己能做。

英文:

You need to read The Go Memory Model

You'll discover that Go has nothing like the control that you have in C++ - there isn't a direct translation of the C++ features in your post. This is a deliberate design decision by the Go authors - the Go motto is Do not communicate by sharing memory; instead, share memory by communicating.

Assuming that the standard go channel isn't good enough for what you want to do, you'll have 2 choices for each memory access, using the facilities in sync/atomic or not, and whether you need to use them or not will depend on a careful reading of the Go Memory Model and analysis of your code which only you can do.

huangapple
  • 本文由 发表于 2015年3月8日 15:29:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/28924132.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定