2016-09-21 67 views
0

跟進this post。我的目標是隻有一個Calculate的時間,所以我增加了一個爲SyncLock:即使您不在單獨的線程中,調用SyncLock和MemoryBarrier是否安全?

Public Sub Calculate(Optional inBack As Boolean = True) 
    If Not inBack Then 
     InternalCalculate(-1, False) 
    Else 
     If CalcThread IsNot Nothing Then 
      CalcThread.Abort() ' yes, I will replace this 
      CalcThread = Nothing ' XXX 
     End If 
     If CalcThread Is Nothing Then 
      CalcThread = New Threading.Thread(AddressOf InternalCalculate) 
      CalcThread.IsBackground = True 
     End If 
     CalcThread.Start() 
    End If 
End Sub 

Private Sub InternalCalculate(Optional Line As Integer = -1, Optional isBack As Boolean = True) 
    Dim Lock As New Object 
    SyncLock Lock 
     Threading.Thread.MemoryBarrier() ' do this BEFORE a write, right? 
     isRunning = true 
     'do the expensive stuff 
    End SyncLock 
End Sub 

注意isBack。如果這是錯誤的,代碼應該在main中運行。當重新計算單個Line時,通常使用這種方法。所以我的問題是關於這兩條線路的安全:

SyncLock Lock 
Threading.Thread.MemoryBarrier() 

這是我不清楚在the documentation如果我在代碼中的主力跑調用這些會發生什麼。我已經添加了代碼,它似乎運行正常,但我想確保我不打開自己到另一個陷阱,如Abort。對於線程和非線程使用都可以嗎?

+0

術語'thread'是'執行線程'的簡稱,簡而言之,一切都是一個線程,因此術語「單線程「爲不使用線程的程序。 'main'本身在一個線程中運行,它可能僅僅是* only *線程,並沒有任何特殊的工作。每個進程都有一個默認/初始線程。 – kfsone

+0

當然,一個* Sync *鎖定用於*同步*線程。如果只有一個線程,則不需要*同步*。因此我的問題。 –

回答

1

是的,在單線程代碼中使用它們是安全的。

但是你的InternalCalculate有問題可以讓它同時執行代碼。每次致電InternalCalculate時都會創建一個新的Lock對象。 Synclock將只會阻止線程,如果這些使用相同的對象,使Lock只讀成員變量。

如果你然後執行多個線程,那麼第二,第三,第四等將等到第一個獲取鎖時退出同步鎖定塊。然後其他人會去。因此,如果這是隻應執行一次的代碼,那麼您應該檢查雙重檢查鎖定模式。

而不是添加MemoryBarriers讀取/寫入易失性數據,我建議您使用System.Threading.Thread.VolatileReadSystem.Threading.Thread.VolatileWrite。那麼你不需要記住你的讀/寫操作的順序。

+0

謝謝@FloatingKiwi!我將盡快修改爲鎖定 - 該代碼直接來自MS示例,我自己對此問題感到好奇。簡單地將聲明移到Sub外部並進入封閉對象就足夠了嗎?我真的需要一個物業嗎? –

+0

後續行動:由於isCalculating bool的消費者遍佈整個應用程序,這是否意味着他們都需要使用VolatileRead?或者是線程內的VolitileWrite足以確保主要的消費者都可以嗎? –

+0

我的建議是隻讀字段,而不是隻讀屬性。這只是表明你正在爲每個類的實例創建一個鎖對象。關於易失代碼,我會重構代碼,以便根本不需要它。比如換算一個返回結果的函數。沒有看到你在計算什麼/你是如何與你的對象進行交互的,這很難說清楚。 – FloatingKiwi

相關問題