使用原子操作而不是线程是否是线程安全的?

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

is using atomic instead of thread thread-safe?

问题

这是一个使用unsafeatomic包来实现的读多写少的参数的例子:

type tmp struct {
}
var value unsafe.Pointer 

func GetValue() *tmp {
    return (*tmp)(atomic.LoadPointer(&value))
}

func SetValue(p *tmp) {
    atomic.StorePointer(&value, unsafe.Pointer(p))
}

这段代码是否是线程安全的?atomic.StorePointer操作是否在atomic.LoadPointer操作之前发生?

英文:

There is a parm which is read more and written less, And I don't want to use a mutex .I got it done like this by unsafe and atomic:

type tmp struct {
}
var value unsafe.Pointer 

func GetValue() *tmp {
    return (*tmp)(atomic.LoadPointer(&value))
}

func SetValue(p *tmp) {
    atomic.StorePointer(&value, unsafe.Pointer(p))
}

Is this thread-safe ? and atomic.StorePointer happen before atomic.LoadPointer ?

答案1

得分: 2

这将在某种意义上是线程安全的,因为你不知道哪个操作会先发生,但更新操作是原子的。你考虑过使用 RWMutex 吗?这样可以在没有写操作时不会锁定读取操作。

英文:

It will be thread safe in the sense that you don't know what happens first, but the updating is atomic. Have you considered using a RWMutex instead? This won't lock readers unless there's a write going on.

答案2

得分: 2

据我所知,使用atomic.LoadPointer和atomic.StorePointer存储和检索指针是线程安全的(指的是指针本身不会被破坏)。

当然,被指向的对象必须是不可变的,这个机制并没有强制执行。在调用UpdateConfig之前,你需要确保更新配置会创建一个新的对象。

然而,主要问题在于该代码依赖于不安全的操作。使其类型安全是困难的,因为实际上需要存储两个指针(一个用于对象,一个用于类型)。仅仅使用原子指针操作已经不足以保证一致性。

这就是为什么最近在sync/atomic包中添加了一个特定类型的原因:sync.Value类型。它的设计目的正是为了实现你想要的功能(即优化对大部分常量数据的访问)。

你可以在这里找到一个示例:http://golang.org/pkg/sync/atomic/#example_Value_config

如果你查看实现,你会意识到仅仅使用原子指针操作是不足以实现类型安全机制的。

英文:

As far as I know, storing and retrieving a pointer using atomic.LoadPointer and atomic.StorePointer is thread-safe (in the sense that the pointer itself will not be corrupted).

Of course, the pointed object must be immutable, and this is not enforced by this mechanism. This is your job to be sure that updating the configuration will result in a new object being created before calling UpdateConfig.

However, the main issue is the code relies on unsafe operations. Making it type safe is difficult, since two pointers have actually to be stored (one for the object, one for the type). Atomic pointer operations are not enough anymore to guarantee the consistency.

This is why a specific type has been recently added in the sync/atomic package: the sync.Value type. It is designed exactly to do what you want (i.e. optimizing access to mostly constant data).

You can find an example here: http://golang.org/pkg/sync/atomic/#example_Value_config

If you look in the implementation, you will realize why atomic pointer operations alone are not enough to implement a type safe mechanism.

答案3

得分: 0

根据https://code.google.com/p/go/issues/detail?id=5045

关于Add/CAS,它应该以更一般的方式来表述,如下所示:在将一个值(包括ADD/CAS)存储到内存位置之后,读取该值的原子操作(包括ADD/CAS)发生。

我认为我们可以使用原子操作来确保线程安全。

英文:

According to https://code.google.com/p/go/issues/detail?id=5045

Regarding Add/CAS, it should be formulated in in more general terms, along the
lines of: at atomic operation that stores a value (incl ADD/CAS) happens before 
atomic operation that reads that value from the memory location (incl ADD/CAS).

I think We can use atomic to ensure it thread-safe.

huangapple
  • 本文由 发表于 2014年12月23日 15:40:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/27616037.html
匿名

发表评论

匿名网友

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

确定