Reputation: 3013
I made a two static classes
NotInheritable Class gObject2
Public Shared TestSyncLock As String = "test"
End Class
NotInheritable Class gObject3
Public Shared TestSyncLock As String = "test"
End Class
Then I have two 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
it works
Everything is good so far.
Now when I go to synclock1.apx and then in another browser got to synclock2.aspx, synclock2.aspx doesn't finish loading until synclock1.aspx finishes.
These are 2 different objects I'm locking with synclock, but it treats them the same. Why is this?
Upvotes: 1
Views: 570
Reputation: 11801
The SyncLock
statement takes an object reference as its argument. As the String
type is a reference type, your code is satisfying that constraint. However, due to String Interning in .Net, the literal value equality of the two separate String
references is also causing referential equality between gObject2.TestSyncLock
and gObject3.TestSyncLock
.
From: String.IsInterned Method - Remarks (emphasis added)
The common language runtime automatically maintains a table, called the intern pool, which contains a single instance of each unique literal string constant declared in a program, as well as any unique instance of String you add programmatically by calling the Intern method.
The intern pool conserves string storage. If you assign a literal string constant to several variables, each variable is set to reference the same constant in the intern pool instead of referencing several different instances of String that have identical values.
Since both gObject2.TestSyncLock
and gObject3.TestSyncLock
are pointing to the same String
reference, SyncLock gObject2.TestSyncLock
will block SyncLock gObject3.TestSyncLock
.
The subject code is a good example of how string interning can cause unexpected behavior. The article Interning Strings and immutability provides additional details on the mechanics of interning and also provides another example where interning can cause unexpected results.
So the moral of this story is to avoid using strings as the argument for SyncLock
. It is safer to use something like the following:
NotInheritable Class gObject2
Public Shared TestSyncLock As New Object
End Class
NotInheritable Class gObject3
Public Shared TestSyncLock As New Object
End Class
Upvotes: 3