2017-04-09 33 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