2017-07-24 127 views
0

我有一个数据golang线程模型比较

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 
} 

是否第二种方法的工作?看来我不需要任何锁定。如果其他线程获得指向旧数据的指针,则管理器更新原始指针就没问题。由于GoLang会执行GC,所有其他线程在读取旧数据后会自动发布。我对么?

+1

只要你的逻辑是对工人的潜力确定以陈旧的数据......这就是说,你如果不这样做可能会惜败自己和一些严重的头痛任何将来的维护完全锁定它,因为读取行为可能是未定义的。一旦开始引发问题,这些问题就很难调试。把它扼杀在萌芽状态并锁定它会更好。 – RayfenWindspear

+1

第二种方法不起作用,因为它在字段“p”上有数据竞争。 –

+0

@CeriseLimón为什么?读者将得到旧的p(这是很好的)或新的p – WhatABeautifulWorld

回答

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) 
}