是使用原子而不是线程线程安全吗?

时间:2014-12-23 07:40:02

标签: go

有一个parm,读取更多,写得更少,而且我不想使用互斥锁。我通过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 happen before atomic.LoadPointer?

3 个答案:

答案 0 :(得分:2)

在某种意义上它是线程安全的,你不知道先发生了什么,但更新是原子的。您是否考虑过使用RWMutex?除非有写入,否则这不会锁定读者。

答案 1 :(得分:2)

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

当然,指向的对象必须是不可变的,并且这种机制不强制执行。这是您的工作,以确保在调用UpdateConfig之前更新配置将导致创建新对象。

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

这就是最近在同步/原子包中添加特定类型的原因:the sync.Value type。它的设计完全符合您的要求(即优化对大多数常量数据的访问)。

您可以在此处找到示例:http://golang.org/pkg/sync/atomic/#example_Value_config

如果你查看implementation,你会发现为什么单独的原子指针操作不足以实现类型安全机制。

答案 2 :(得分:0)

根据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).

我认为我们可以使用atomic来确保它是线程安全的。