Aaron Brown
Aaron Brown

Reputation: 291

SyncLock the same object from two different threads

Basically I have a global variable, such as...

Dim int1 as integer

And then I have two asynchronous functions, such as...

function bleh()
    int1 += 1
end function

and

function Meh()
     int1 -= 1
end function

Both these functions are being run by Task.Run().

I want to use SyncLock in both these functions. However, all the examples given on the MSDN site only show examples of SyncLock being used within a single function. So I can't tell simply from the MSDN description if it is "okay" for me to use SyncLock across two different functions, on a global variable.

What I want to do is something like this:

Private Shared SyncObj as Object '<-- global
Dim int1 as integer '<-- global

Sub Form_Load(...)
     SyncObj = new Object
     Task.Run(Function() bleh())
     Task.Run(Function() Meh())
End Sub

Function bleh()
     SyncLock SyncObj
        int1 += 1
     End SyncLock
End Function
Function Meh()
     SyncLock SyncObj
        int1 -= 1
     End SyncLock
End Function

Is this okay to do? Will bleh() block Meh() from changing int1, and vise versa? Thanks! Sorry for the VB lol.

Upvotes: 0

Views: 8678

Answers (1)

Carlos Landeras
Carlos Landeras

Reputation: 11063

Yeah It is OK. SyncLock is designed for that. It avoids other thread accessing to a resource while other thread is working with it. I recommend you to do a Console.Writeline or Debug.Writeline to follow its output.

Add a While true to check how the values are changing:

Sub Form_Load(...)
     SyncObj = new Object
     While true
      Task.Run(Function() bleh())
      Task.Run(Function() Meh())
     End while     
End Sub

Function bleh()
     SyncLock SyncObj
        int1 += 1
        Debug.Writeline("from thread bleh: " & int1.toString)
     End SyncLock
End Function
Function Meh()
     SyncLock SyncObj
        int1 -= 1
         Debug.Writeline("from thread meh: " & int1.toString)
     End SyncLock
End Function

The Synclock, will prevent bleh() to access that code while meh() is working with it, and viceversa.

EDIT: I executed your code and this is the output:

from thread meh: -1

from thread meh: -2

from thread bleh: -1

from thread bleh: 0

from thread bleh: 1

from thread meh: 0

from thread bleh: 1

from thread meh: 0

from thread bleh: 1

from thread meh: 0

from thread meh: -1

from thread bleh: 0

from thread bleh: 1

from thread meh: 0

from thread bleh: 1

from thread bleh: 2

from thread meh: 1

from thread meh: 0

from thread meh: -1

from thread bleh: 0

You block the access to int1, but you can't control one thread to execute two times before the other one is triggered as you can see.

This could be useful using another Example, for example with a File, It can't be accesed from two threads at a time or it will give a exception.

Here you have the example:

 Imports System.Threading.Tasks
Imports System.IO

Module Module2

    Dim SyncObj As Object

    Dim path As String = "c:\testfile.text"
    Sub Main()

        SyncObj = New Object
        While True
            Task.Factory.StartNew(Function() bleh())
            Task.Factory.StartNew(Function() Meh())
        End While
    End Sub

    Function bleh()
        SyncLock SyncObj

            Using sw As New StreamWriter(path, True)
                sw.WriteLine("From bleh!!!")
            End Using
        End SyncLock
    End Function
    Function Meh()
        SyncLock SyncObj
            Using sw As New StreamWriter(path, True)
                sw.WriteLine("From meh!!!")
            End Using
        End SyncLock
    End Function

End Module

This example wrote 26814 lines on the path file without any exception in some seconds, so concurrent access to the resource did not happen.

Upvotes: 5

Related Questions