2017-04-09 129 views
0

我做了兩個靜態類試圖瞭解的SyncLock是如何工作的

NotInheritable Class gObject2 
    Public Shared TestSyncLock As String = "test" 
End Class 

NotInheritable Class gObject3 
    Public Shared TestSyncLock As String = "test" 
End Class 

然後我有兩個ASPX

Synclock1.aspx:

Public Class SyncLock1 
    Inherits System.Web.UI.Page 

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
     SyncLock gObject2.TestSyncLock 
      Thread.Sleep(10000) 
     End SyncLock 
    End Sub 

End Class 

Synclock2.aspx

Public Class SyncLock2 
    Inherits System.Web.UI.Page 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

     SyncLock gObject3.TestSyncLock 
      SomeDiv.InnerHtml = "It works" 
     End SyncLock 
    End Sub 
End Class 
  1. 當我轉到synclock1.aspx時,它會旋轉10秒,並按預期顯示空白頁。
  2. 當我去synclock2.aspx它吐出it works

一切已經很不錯了。

現在,當我去synclock1.apx然後在另一個瀏覽器中得到了synclock2.aspx,synclock2.aspx無法完成加載,直到synclock1.aspx完成。

這些是我用synclock鎖定的2個不同的對象,但它將它們視爲相同。爲什麼是這樣?

+1

如果將其中一個字符串更改爲'test123',會發生什麼?也許'SyncLock'做了一個正常的比較而不是參考比較? –

+0

@VisualVincent我認爲你的建議是完全基於離線的,但是當我將字符串從'test'改爲'test123'時,它工作正常。 – Henry

+2

推測它在幕後使用了'Object.Equals',並且會測試'String'類型的值相等。我會建議專門爲鎖定而創建的對象應該只是鍵入'Object'。如果他們只是爲了鎖定而存在,那麼他們不應該有任何數據,因爲這些數據可能沒有用處。 – jmcilhinney

回答

2

SyncLock語句將對象引用作爲其參數。由於String類型是引用類型,因此您的代碼正在滿足該約束。但是,由於.Net中的String Interning,兩個單獨的String引用的文字值相等也導致gObject2.TestSyncLockgObject3.TestSyncLock之間的引用相等。

來源:String.IsInterned Method - Remarks(強調)

公共語言運行時自動保持一個表,稱爲 實習生池,其中包含在一個程序中聲明的每個唯一 文字字符串常量的單個實例,如以及通過調用實體 方法以編程方式添加的任何獨特的 字符串實例。

實習生池保存字符串存儲。 如果分配字面 字符串常量幾個變量,每個變量被設置爲參考 相同的恆定在實習生池而不是引用字符串的具有相同值的幾個 不同的實例。

由於兩個gObject2.TestSyncLockgObject3.TestSyncLock都指向同一String參考,SyncLock gObject2.TestSyncLock將阻止SyncLock gObject3.TestSyncLock

主題代碼是字符串實習可能導致意外行爲的一個很好的例子。文章Interning Strings and immutability提供了有關實習機制的更多詳細信息,並提供了另一個實習可能導致意外結果的例子。

所以這個故事的寓意是避免使用字符串作爲SyncLock參數。使用如下所示的更安全:

NotInheritable Class gObject2 
    Public Shared TestSyncLock As New Object 
End Class 

NotInheritable Class gObject3 
    Public Shared TestSyncLock As New Object 
End Class