2017-07-24 52 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) 
}