General question about synclock

DanielB33

Active member
Joined
Mar 29, 2013
Messages
40
Programming Experience
1-3
Thank to all for continuing to look over my posts. Everyone has been a great help.

I have an array that I fill with data in my main class. I also have a global index tracking where I am at in my array.

In another class, I decrement this index and use the information. The goal is simply to track where I am 'at' in terms of gathered information verses used information.

What if I am adding data to my array and incrementing my counter WHILE I am decrementing my counter in the other array? Do I need a synclock? If so could someone try to explain how to use it as if to a complete newb? I am very familiar with embedded systems but have just been learning as I go with GUI. Never taken a class or anything. I have been reading online but still do not feel confident enough to write the code expecting it to work.

Thanks for the help.
 
Think of threads as people who all want to use a particular resource and a SyncLock block as a room containing that resource that only one person can enter at a time. That ensures that one thread has finished what it was doing before another starts doing something with the resource.

There's more to SyncLock though. You can have multiple SyncLock statements that all lock on the same object, in which case only one thread can be in any of them at a time. If one thread enters one block then another thread can't enter that block or any other that locks on the same object until the first thread exits.

Furthermore, even the same thread can't enter two SyncLock blocks that lock on the same object or the same SyncLock twice. As a result, you can create a deadlock with a single thread. Imagine that you have a recursive method with a SyncLock inside it. Execution enters the method and then enters the SyncLock. It hits the recursive call within the SyncLock block so it, without exiting the SyncLock, the same thread enters the same method again and then it has to wait at the SyncLock. It can't pass the SyncLock statement because a thread has already entered that SyncLock block. It's the same thread though, therefore it will wait indefinitely because it can never enter because it will never exit.

So, deadlocks are the main thing to be wary of when using SyncLock. Here's a simple example:
Private counter As Integer
Private ReadOnly syncRoot As New Object

Private Sub IncrementCounter()
    SyncLock syncRoot
        counter += 1
    End SyncLock
End Sub

Private Sub DecrementCounter()
    SyncLock syncRoot
        counter -= 1
    End SyncLock
End Sub
It's a good convention to follow to explicitly create an Object specifically for the purpose of locking and to assign it to a variable named 'syncRoot'. This example is somewhat contrived because, if all you want to do is increment and decrement an Integer, you can use the Interlocked class, which handles the thread synchronisation for you.
 
Thanks for the reply. It makes more sense now, but I still do not fully understand. I don't understand the concept of dead lock. If the purpose of synclock is to prevent multiple accesses of code simultaneously, it seems rather contradictory for a dead lock to be able to occur How is this even possible if two accesses to a synclocked object cannot access it at the same time? Pease tell me if I am using the following code properly.

'BELOW IS CODE FOR DATALOGGING EXPORT SEQUENCE.


'This is separate logic from sequence above. Above is simply for real time display update. Below we implement circular buffer.


SyncLock syncRoot


Circ_Buff(Circ_Buff_Head_Index) = recievedString_Split(incriment).ToString



'Wrap head back to beginning of array



If Circ_Buff_Head_Index >= CIRC_BUFF_SIZE Then
Circ_Buff_Head_Index = 0


EndIf
Circ_Buff_Head_Index += 1
EndSyncLock


The code above is called every 15.6ms in main.vb. In another form, I check the circular buffer every 15.6ms or so as well and access circ_buff. This in a different thread, should I create another synclock? Am I on the right track?
 
A deadlock cannot occur if all you have is one SyncLock block and each thread only tries to enter it once. A deadlock can also not occur if you have one SyncLock block and you have one or more threads that try to enter it more than once. I thought it could but I just tested this:
Public Class Form1

    Private ReadOnly syncRoot As New Object

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Method1()
    End Sub

    Private Sub Method1()
        SyncLock syncRoot
            MessageBox.Show("Method1")
            Method2()
        End SyncLock
    End Sub

    Private Sub Method2()
        SyncLock syncRoot
            MessageBox.Show("Method2")
        End SyncLock
    End Sub

End Class
and it worked fine. Obviously a thread can pass a SyncLock statement that locks on an object that that same thread has already claimed.

Where a deadlock can occur is where you have two or more SyncLock blocks that lock on different objects and two or more threads that try to lock on two or more of those objects. In this example:
Imports System.Threading

Public Class Form1

    Private ReadOnly syncRoot1 As New Object
    Private ReadOnly syncRoot2 As New Object

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim t1 As New Thread(AddressOf Method1A)
        Dim t2 As New Thread(AddressOf Method2A)

        t1.Start()
        t2.Start()
    End Sub

    Private Sub Method1A()
        SyncLock syncRoot1
            Console.WriteLine("Method1A")
            Method1B()
        End SyncLock
    End Sub

    Private Sub Method1B()
        SyncLock syncRoot2
            Console.WriteLine("Method1B")
        End SyncLock
    End Sub

    Private Sub Method2A()
        SyncLock syncRoot2
            Console.WriteLine("Method2A")
            Method2B()
        End SyncLock
    End Sub

    Private Sub Method2B()
        SyncLock syncRoot1
            Console.WriteLine("Method2B")
        End SyncLock
    End Sub

End Class
a deadlock may occur, depending on the timing of each thread. Thread t1 may enter Method1A and claim a lock on syncRoot1 and thread t2 may enter Method2A and claim a lock on syncRoot2. Once that happens, we're screwed. Thread t1 will then enter Method1B and have to wait because it can't claim a lock on syncRoot2 and thread t2 will enter Method2B and have to wait because it can't claim a lock on syncRoot1. Both threads are waiting to claim a lock on an object already claimed by the other but neither will give up the lock they have until they can claim the other. Tada... deadlock.
 
jmcilhinney said:
Obviously a thread can pass a SyncLock statement that locks on an object that that same thread has already claimed.
Logically one thread can only execute one statement at a time, so it doesn't need synchronization protection against itself. SyncLock uses Monitor.Enter, which says:
It is legal for the same thread to invoke Enter [on the object] more than once without it blocking
 
Back
Top