此問題的一個示例是用戶創建資源並刪除資源。我們將執行操作並增加(遞減)計數器緩存。如何去測試去例程?
在測試中,有時會出現競爭狀態,計數器緩存並未由go例程更新。
編輯:抱歉的混亂,澄清:計數器緩存不在內存中,它實際上是數據庫中的字段。競爭條件不是內存中的變量,實際上goroutine可能會很慢寫入數據庫本身!
我目前在操作後使用1秒睡眠來確保計數器緩存在測試計數器緩存之前已經更新。有沒有另外一種方法來測試沒有任意1秒睡眠的例行程序,以等待去程序完成?
乾杯
此問題的一個示例是用戶創建資源並刪除資源。我們將執行操作並增加(遞減)計數器緩存。如何去測試去例程?
在測試中,有時會出現競爭狀態,計數器緩存並未由go例程更新。
編輯:抱歉的混亂,澄清:計數器緩存不在內存中,它實際上是數據庫中的字段。競爭條件不是內存中的變量,實際上goroutine可能會很慢寫入數據庫本身!
我目前在操作後使用1秒睡眠來確保計數器緩存在測試計數器緩存之前已經更新。有沒有另外一種方法來測試沒有任意1秒睡眠的例行程序,以等待去程序完成?
乾杯
在測試中,有時存在的競爭條件,使計數器緩存沒有被旅途例行更新。我目前在操作之後使用1秒睡眠來確保在測試計數器緩存之前計數器緩存已經被更新。
哎呀,我討厭這麼說,但你做錯了。 Go具有一流的功能,使併發變得輕鬆!如果你正確使用它們,就不可能有競爭條件。
事實上,有一個工具,將detect races for you。我敢打賭,它抱怨你的計劃。
一個簡單的解決方案:
(另一種方法是使用鎖。這將是更高性能的一點點,但更麻煩的編寫,並確保它是正確的。)
對此感到抱歉,澄清一下:計數器緩存不在內存中,它實際上是數據庫中的一個字段。競爭條件不是內存中的變量,實際上goroutine可能會很慢寫入數據庫本身! – samol
@SidneySidaZhang是的,爲此你需要同步。爲此,還有像頻道這樣的工具,如果必須的話,還有鎖。你只能保證你的代碼按照正確的順序執行,如果它是同步的。數據所在的位置並不重要,它是如何獲得重要信息的方式。 – nemo
如果您在寫完結果後需要閱讀結果,則無法在不同的程序中進行寫入和讀取。 – BraveNewCurrency
一種解決方案是讓讓你還價只要值 更改,就會更新頻道。通常情況下,通過傳達結果進行同步。例如您 Couter
看起來是這樣的:
type Counter struct {
value int
ValueChange chan int
}
func (c *Counter) Change(n int) {
c.value += n
c.ValueChange <- c.value
}
每當Change
被調用時,新的值通過通道時和誰是 等待值疏導,並繼續執行,因此與 計數器同步。有了這個代碼,你可以在ValueChange
聽這樣的變化:
v := <-c.ValueChange
同時呼籲c.Change
是沒有問題了。
一小段代碼示例會很好。我試圖擺脫睡眠和競爭狀態,但無法猜測你的代碼是什麼樣的。假設尚未使用,那麼聽起來像頻道是你需要的。 – miltonb
我第二@米爾頓的觀點。在代碼中引入睡眠以「修復」數據競爭通常不是正確的解決方案。一旦你的系統負載很重,超過一秒鐘就會通過生產,然後睡眠不起作用。安全構建這些系統的唯一方法是同步。同步通常涉及到某個通道使用信號發送安全寫回信號。 –