我有一段数据
type data struct {
// all good data here
...
}
此数据由管理员拥有,并由其他线程用于只读。经理需要定期更新数据。如何为此设计线程模型?我可以想到两个选择:
1
type manager struct {
// acquire read lock when other threads read the data.
// acquire write lock when manager wants to update.
lock sync.RWMutex
// a pointer holding a pointer to the data
p *data
}
2。
type manager struct {
// copy the pointer when other threads want to use the data.
// When manager updates, just change p to point to the new data.
p *data
}
第二种方法有效吗?看来我不需要任何锁定。如果其他线程获得指向旧数据的指针,那么如果manager更新原始指针则没问题。由于GoLang将执行GC,在所有其他线程读取旧数据后,它将自动释放。我是对的吗?
答案 0 :(得分:1)
你的第一个选择很好,也许最简单。但是,它可能导致许多读者的表现不佳,因为它可能很难获得写锁定。
正如您对问题的评论所述,您的第二个选项(原样)会导致竞争状况并导致不可预测的行为。
您可以使用atomic.Value实施第二个选项。这将允许您将指针存储到某个数据结构并以原子方式更新它以供下一个读者使用。例如:
// Data shared with readers
type data struct {
// all the fields
}
// Manager
type manager struct {
v atomic.Value
}
// Method used by readers to obtain a fresh copy of data to
// work with, e.g. inside loop
func (m *manager) Data() *data {
return m.v.Load().(*data)
}
// Internal method called to set new data for readers
func (m *manager) update() {
d:=&data{
// ... set values here
}
m.v.Store(d)
}