SpinLock VB.Net Example From MSDN Possibly Produces Incorrect Behaviour
The code below is part of an example from MSDN. It is the example on how to use SpinLock but to my eye there is a race condition in it.
Why I think this is because of the Dim lockTaken As Boolean = False line in the UpdateWithSpinLock method. It appears to me that the following could occur:
Thread 1 enters UpdateWithSpinLock method and executes as far as _queue.Enqueue(d) and a context switch occurs.
Thread 1 now has the SpinLock and lockTaken is True.
Thread 2 enters and only executes as far as the line Dim lockTaken As Boolean = False.
Thread 2 has now set lockTaken back to False and a context switch occurs.
Thread 1 continues and tests lockTaken in the Finally block and finds it to be False (it should be True for Thread 1) so doesn't release the SpinLock.
Thread 1 exits the method leaving the lock inplace and thread 2 waiting forever.
Imports System.Threading
Imports System.Threading.Tasks
Class SpinLockDemo2
Const N As Integer = 100000
Shared _queue = New Queue(Of Data)()
Shared _lock = New Object()
Shared _spinlock = New SpinLock()
Class Data
Public Name As String
Public Number As Double
End Class
Shared Sub Main()
UseSpinLock()
Console.WriteLine("Press a key")
Console.ReadKey()
End Sub
Private Shared Sub UpdateWithSpinLock(ByVal d As Data, ByVal i As Integer)
Dim lockTaken As Boolean = False
Try
_spinlock.Enter(lockTaken)
_queue.Enqueue(d)
Finally
If lockTaken Then
_spinlock.Exit(False)
End If
End Try
End Sub
Private Shared Sub UseSpinLock()
Dim sw = Stopwatch.StartNew()
Parallel.Invoke(
Sub()
For i As Integer = 0 To N - 1
UpdateWithSpinLock(New Data() With {.Name = i.ToString(), .Number = i}, i)
Next
End Sub,
Sub()
For i As Integer = 0 To N - 1
UpdateWithSpinLock(New Data() With {.Name = i.ToString(), .Number = i}, i)
Next
End Sub
)
sw.Stop()
Console.WriteLine("elapsed ms with spinlock: {0}", sw.ElapsedMilliseconds)
End Sub
Shared Sub UpdateWithLock(ByVal d As Data, ByVal i As Integer)
SyncLock (_lock)
_queue.Enqueue(d)
End SyncLock
End Sub
Private Shared Sub UseLock()
Dim sw = Stopwatch.StartNew()
Parallel.Invoke(
Sub()
For i As Integer = 0 To N - 1
UpdateWithLock(New Data() With {.Name = i.ToString(), .Number = i}, i)
Next
End Sub,
Sub()
For i As Integer = 0 To N - 1
UpdateWithLock(New Data() With {.Name = i.ToString(), .Number = i}, i)
Next
End Sub
)
sw.Stop()
Console.WriteLine("elapsed ms with lock: {0}", sw.ElapsedMilliseconds)
End Sub
End Class
Is the way I'm interpreting this correct. If it's not could you please show me what I'm missing.
Thanks in advance.
0 comments:
Post a Comment
Thanks