|
-
Dec 23rd, 2009, 08:30 AM
#1
Thread Starter
Hyperactive Member
how to check if Mutex is Released
i've got a Set and a Get in a property. I want to allow multiple threads to do Get anytime they wish to, however if any thread tries to do Set, all threads must not be able to Get/Set until the Set is complete.
what i tried is this (lock is a Mutex):
Code:
Public Shared Property someproperty() As Boolean
Get
lock.WaitOne()
lock.ReleaseMutex()
Return VAR_propvalue
End Get
Set(ByVal value As Boolean)
lock.WaitOne()
VAR_propvalue = value
lock.ReleaseMutex()
End Set
End Property
the problem is that this is pretty inefficient because each request to Get will steal the Mutex and prevent other Gets until the stolen Mutex is Released.
Is there anyway to just check if a Mutex is released instead of using WaitOne because WaitOne checks and gains control of the Mutex which is not what i want
-
Dec 23rd, 2009, 09:05 AM
#2
Hyperactive Member
Re: how to check if Mutex is Released
I think 'Synclock' is what you are looking for. When you place synclock on a object, all other threads that want to access it will have to wait untill the synclock is gone.
Code:
Public Shared Property someproperty() As Boolean
Get
Return VAR_propvalue
End Get
Set(ByVal value As Boolean)
SyncLock VAR_propvalue
VAR_propvalue = value
End SyncLock
End Set
End Property
ps: If you want some more control, like skipping some code when a synclock is active. Try using Threading.Monitor.TryEnter. This will return true or false depending on if a object is locked.
Last edited by gonzalioz; Dec 23rd, 2009 at 09:10 AM.
-
Dec 23rd, 2009, 09:44 AM
#3
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
the synclock would do fine, however it doesn't allow me to Sync primitive types (boolean)
-
Dec 23rd, 2009, 09:47 AM
#4
Re: how to check if Mutex is Released
I've never used it before but I think you should simply declare a new Object and use that, something like this:
Code:
Dim obj As New Object()
Public Shared Property someproperty() As Boolean
Get
Return VAR_propvalue
End Get
Set(ByVal value As Boolean)
SyncLock obj
VAR_propvalue = value
End SyncLock
End Set
End Property
Whether this is the right approach in a property, I've no idea.
-
Dec 23rd, 2009, 09:49 AM
#5
Hyperactive Member
Re: how to check if Mutex is Released
 Originally Posted by NickThissen
I've never used it before but I think you should simply declare a new Object and use that, something like this:
Code:
Dim obj As New Object()
Public Shared Property someproperty() As Boolean
Get
Return VAR_propvalue
End Get
Set(ByVal value As Boolean)
SyncLock obj
VAR_propvalue = value
End SyncLock
End Set
End Property
Whether this is the right approach in a property, I've no idea.
That's ugly .
-
Dec 23rd, 2009, 10:27 AM
#6
Re: how to check if Mutex is Released
 Originally Posted by gonzalioz
That's ugly  .
That's the only way I've ever seen it used; with a new object purely for synclocking. Do you suggest another way?
-
Dec 23rd, 2009, 10:43 AM
#7
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
currently i'm doing something like this:
i wonder which is uglier:
Code:
Get
Do While VAR_busy_setting_permissions
Loop
Return VAR_value
End Get
-
Dec 23rd, 2009, 06:29 PM
#8
Re: how to check if Mutex is Released
currently i'm doing something like this:
i wonder which is uglier:
Using a loop like that is definitely uglier if you ask me... and much more processor intensive. I would recommend not doing that.
I've never used it before but I think you should simply declare a new Object and use that, something like this:
Code:
Dim obj As New Object()
Public Shared Property someproperty() As Boolean
Get
Return VAR_propvalue
End Get
Set(ByVal value As Boolean)
SyncLock obj
VAR_propvalue = value
End SyncLock
End Set
End Property
Whether this is the right approach in a property, I've no idea.
Yeah that is how you should use it (that is how I have always used it and have never had any problems and that is how every example I have ever seen has used it), although you would normally put the Get in a SyncLock as well as otherwise another thread could read the property while it is still part way through being set.
Anyway, I dont think any kind of lock is really necessary for a boolean as there is no 'inconsistent' state for it to be in. Generally the purpose of sync locks or mutex etc is to prevent one thread from modifying something while another thread is using it, like with a list for example one thread could be looping through the list and then another thread could remove all of the items - so the list is then in an inconsistent state when the original thread comes to loop to the next item and finds that it no longer exists (and it will throw an exception because the collection has been modified). With a boolean though, you cant really get that problem as its just either True or False and nothing in between.
Having said that, you might just be using the Boolean as an example so I'll still give you my thoughts on the original question - I would agree that a SyncLock block is the best way to handle this, but just using SyncLock on its own you will still have the same issue of only one thread being allowed in either the Get or Set at any one time. So perhaps you could do something like this:
Code:
'Example:
Private InSet As Boolean = False
Private Lock As New Object
Private _SomeString As String
Public Property SomeString() As String
Get
If InSet Then
SyncLock Lock
Return _SomeString
End SyncLock
Else
Return _SomeString
End If
End Get
Set(ByVal value As String)
InSet = True
SyncLock Lock
_SomeString = value
End SyncLock
InSet = False
End Set
End Property
-
Dec 23rd, 2009, 08:54 PM
#9
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
btw does using a loop really take up alot of resources?
does SyncLock also make use of a loop internally?
-
Dec 24th, 2009, 06:15 AM
#10
Re: how to check if Mutex is Released
try it yourself, create a new project and just stick this in the form load event handler and then check task manager when you launch the program:
Code:
Dim Something As Boolean = False
Do Until Something = True
Loop
Oh and good luck ever getting the form to actually appear on screen :P
As for SyncLock, no I do not think that uses a loop behind the scenes. It certainly does not cause the CPU usage to shoot up when a thread is waiting for a lock to be released so that it can enter the SyncLock section. Take a look at this page for more info: http://msdn.microsoft.com/en-us/libr...1t(VS.80).aspx
Last edited by chris128; Dec 24th, 2009 at 06:25 AM.
-
Dec 24th, 2009, 07:32 AM
#11
Hyperactive Member
Re: how to check if Mutex is Released
When synclock is active, other threads will be stored into a 'waiting queue' or whatever you want to call it. Just doing nothing. When End Synclock is used the first thread in the queue will be be punched in the face to wake him up and he will continue where he left of.
So the threads that are waiting aren't asking the other thread that holds the lock. Are you done yet, are you done yet, constantly. They just say, hey I'll wait here in this queue. Give me a signal when your done .
-
Dec 24th, 2009, 10:00 AM
#12
Re: how to check if Mutex is Released
 Originally Posted by gonzalioz
When synclock is active, other threads will be stored into a 'waiting queue' or whatever you want to call it. Just doing nothing. When End Synclock is used the first thread in the queue will be be punched in the face to wake him up and he will continue where he left of.
So the threads that are waiting aren't asking the other thread that holds the lock. Are you done yet, are you done yet, constantly. They just say, hey I'll wait here in this queue. Give me a signal when your done  .
You know I thought that, and I even typed pretty much the same thing in my last post... but then I edited it because I'm not so sure now. SyncLock is just a nice tidy way of using the Monitor class - this is taken from the MSDN description of the System.Threading.Monitor class:
The functionality provided by the Enter and Exit methods is identical to that provided by the C# lock statement (SyncLock in Visual Basic), except that lock and SyncLock wrap the Exit method in a try…finally block (Try…Finally in Visual Basic) to ensure that the monitor is released.
so I'm trying to find out exactly how the Monitor class works behind the scenes but not having much joy... I checked it out in Reflector but the Monitor.Enter method just shows as this:
Code:
<MethodImpl(MethodImplOptions.InternalCall)> _
Public Shared Sub Enter(ByVal obj As Object)
and that MethodImplOptions.InternalCall parameter basically means that this particular method is actually implemented in unmanaged code so I am going to download the source code for .NET 2.0 that Microsoft released and see if I can find anything about it in there. I guess this is straying away from the OP's question slightly now but I am curious about how Monitors work as there is no such object in the underlying Windows OS (there are Mutexes and Semaphores but no such thing as a Monitor as far as I know).
-
Dec 24th, 2009, 10:52 AM
#13
Re: how to check if Mutex is Released
OK so I have been doing some digging and think I might finally be getting somewhere towards an informed answer to how SyncLock/Monitor.Enter works 
As I mentioned in the last post, classes like Mutex and Semaphore are just wrappers around existing objects in the Windows OS, but a Monitor (and therefore the SyncLock function) does not exist in the Windows OS and is a pure .NET feature. I say 'pure' but the implementation of the Monitor's methods is actually written in unmanaged C++ code.
Anyway, basically any object that is constructed in .NET has a header in memory which contains a few fields and one of these fields is a SyncBlockIndex (thats SyncBlock not SyncLock). It looks like the .NET runtime keeps a load of these SyncBlock items in memory and basically each time you use SyncLock/Monitor.Enter on an object, the CLR associates one of these 'spare' SyncBlocks with the object you passed to SyncLock/Monitor.Enter. It does this by entering the SyncBlock's ID into the object's SyncBlockIndex field. Then when your code calls End SyncLock or Monitor.Exit then the locking object's SyncBlockIndex field is set back to a negative number to indicate that it has no SyncBlock associated with it.
So if another thread comes along and calls SyncLock/Monitor.Enter on this same object then it will see that the SyncBlockIndex field of the object is set and it will look at the SyncBlock that this field points to - if it sees that this SyncBlock is owned by another thread then it will suspend this thread and wait for the other thread to release the SyncBlock so that it can then take ownership.
So in short, I dont THINK using SyncLock incurs any kind of looping or intensive CPU usage, although I did read somewhere that it will check the SyncBlock ownership again a few times quickly before resorting to suspending the thread - presumably because sometimes the SyncBlock will have been released a few miliseconds later so it would be less efficient to suspend the thread and wait for the notification than it would be to just try again a few times first.
Well, I found it interesting even if no one else did 
Oh and if anyone has anything to add to that or correct, please do!
Chris
-
Dec 24th, 2009, 11:27 AM
#14
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
i think the code u provided above would not work:
Code:
Get
If InSet Then
SyncLock Lock
Return _SomeString
End SyncLock
Else
Return _SomeString
End If
End Get
because after you have Returned, everything else below it does not run. So the Lock never gets released. so what we have is this:
Code:
Get
If InSet Then
SyncLock Lock
End SyncLock
Return _SomeString
Else
Return _SomeString
End If
End Get
there's 2 reasons why i do not wish to use SyncLock. number one is obviously we are created an object for just Synclocking, another and more Importantly is that there is a delay in SyncLock compared to using the Do While method.
During:
Code:
SyncLock Lock
End SyncLock
the thread steals priority and prevents other from reading. So if i had like 10 threads trying to do a Get, i want them to be able to occur simultaneously, in any order, because it would still be ThreadSafe (unless someone decides to do a Set). But using SyncLock, the 10 threads had to do it one by one, even if its fast, its still one by one, whereas Do While allows all of them to do Straight away without waiting for any
Code:
Do While allowed_to_do_a_get
Loop
Well of course 0 loops are taking place if allowed_to_do_a_get is set to True. I think the real problem is that alot of loops will take place if someone is Setting (which will set allowed_to_do_a_get to false)
Is there a better way to do things, a SyncLock that doesn't cause delay?
also,
if it sees that this SyncBlock is owned by another thread then it will suspend this thread and wait for the other thread to release the SyncBlock so that it can then take ownership.
so how does he actually know that the SyncBlock is released, doesn't he have to check it every now and then to see if SyncBlock is released? (which means a loop)
Last edited by pacerier; Dec 24th, 2009 at 11:36 AM.
-
Dec 24th, 2009, 11:54 AM
#15
Re: how to check if Mutex is Released
"although I did read somewhere that it will check the SyncBlock ownership again a few times quickly before resorting to suspending the thread - presumably because sometimes the SyncBlock will have been released a few miliseconds later so it would be less efficient to suspend the thread and wait for the notification than it would be to just try again a few times first."
I think what is fundamental to any synchronizing operation is the hardware's ability to do a read-alter-rewrite operation atomically.
-
Dec 24th, 2009, 12:44 PM
#16
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
i've currently upgraded my Do While to slow down depending on user input.
'gap is an Integer specifying the wait time
Code:
Do While allowed_to_do_a_get
If gap <> 0I then
Threading.Thread.Sleep(gap)
End If
Loop
-
Dec 24th, 2009, 04:15 PM
#17
Re: how to check if Mutex is Released
I am just missing something. You have a property that can be true or false, and you are trying to make certain that only one process is able to set it, and you do not want it to be read while it is being set.
Don't make this more complicated than it is:
Code:
'to Set it
SyncLock lock
flag = True
End SyncLock
'or
Monitor.Enter(lock)
flag = True
Monitor.Exit(lock)
'to Read it
Dim retval As Boolean
SyncLock lock
retval = True
End SyncLock
'or
Monitor.Enter(lock)
retval = True
Monitor.Exit(lock)
-
Dec 24th, 2009, 06:41 PM
#18
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
no its not just one property, its 2 (and it can be more), of course i do not wish it to be read while its being written. If some thread is writing it halfway, how could i allow it to be read? it can only be read until the write is over, unless there is no one writing, then any amount of threads can read it anyhow they want.
plus if 1 or more threads are reading, no threads should be allowed to do a Write, untill the read is complete, to ensure that the read is proper
-
Dec 24th, 2009, 06:50 PM
#19
Re: how to check if Mutex is Released
 Originally Posted by pacerier
i think the code u provided above would not work:
Code:
Get
If InSet Then
SyncLock Lock
Return _SomeString
End SyncLock
Else
Return _SomeString
End If
End Get
because after you have Returned, everything else below it does not run. So the Lock never gets released. so what we have is this:
Code:
Get
If InSet Then
SyncLock Lock
End SyncLock
Return _SomeString
Else
Return _SomeString
End If
End Get
No that is not the case, when you come out of the scope of a SyncLock block the lock will be released - it doesnt have to actually hit the End SyncLock line. Just like if you use a Using statement, you dont have to hit the End Using line for the object to be disposed, its just when you come out of the scope of that statement. I assume this behaviour is achieved by the fact that internally the SyncLock uses a Try/Catch/Finally block and releases the lock in the Finally block. You can see the same behaviour yourself if you just do something like this inside a Function:
vb.net Code:
Try
Dim something As String = "Some text"
Return something
Catch
MessageBox.Show("Oh dear")
Finally
MessageBox.Show("Merry Christmas") 'seasonal examples FTW
End Try
Now if you run that function you will see that you get your 'something' object returned but the Finally block is still reached so you should still see the Merry Christmas message box
Last edited by chris128; Dec 24th, 2009 at 06:54 PM.
-
Dec 24th, 2009, 06:59 PM
#20
Re: how to check if Mutex is Released
Also, I have been assuming all along that you are just trying to make your code as efficient as is physically possible, but if the reason for you asking about this is because you are worried about this slowing your application down then I would say you have nothing to worry about unless you are making an extremely performance sensitive application. I have made plenty of applications that use several threads (some that use up to 20 at once) and have never had any performance problems with SyncLock at all and I'm sure most other developers would agree.
Also, a Property should never really be doing anything that takes a long time in its Set or Get methods, so your other threads should only ever be waiting a fraction of a second if there is another thread already inside either the Get or the Set.
-
Dec 24th, 2009, 07:10 PM
#21
Re: how to check if Mutex is Released
As Chris pointed out, performance in the case you have provided, or even if there are several properties, should not be an issue.
You might also try
Code:
Dim flag As Long
'set
Interlocked.CompareExchange(flag, 1, 0)
'get
Interlocked.Read(flag)
'clear
Interlocked.CompareExchange(flag, 0, 1)
-
Dec 24th, 2009, 08:18 PM
#22
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
if the reading thread had to steal priority as well, in other words, is it true that what a SyncLock can do, a Mutex can do as well?
-
Dec 24th, 2009, 08:32 PM
#23
Re: how to check if Mutex is Released
 Originally Posted by pacerier
if the reading thread had to steal priority as well, in other words, is it true that what a SyncLock can do, a Mutex can do as well?
You could make a Mutex and SyncLock both do the same thing yes, but its much easier, more maintainable, more readable, and the more ".NET way of doing things" to just use SyncLock if you ask me.
-
Dec 24th, 2009, 08:33 PM
#24
Re: how to check if Mutex is Released
"You could make a Mutex and SyncLock both do the same thing yes, but its much easier, more maintainable, more readable, and the more ".NET way of doing things" to just use SyncLock if you ask me."
Certainly in this case I agree.
-
Dec 24th, 2009, 08:34 PM
#25
Re: how to check if Mutex is Released
Also, a Mutex is slower than SyncLock according to this article: http://blogs.techrepublic.com.com/pr...elopment/?p=86
A word of warning: as the test result show, Mutex is an extremely slow system! You want to be very careful when using Mutex. According to MSDN Magazine (September, 2006), Mutex can take 9801.6 CPU cycles to acquire a lock on a CPU without contention. In comparison to 112 CPU cycles for a Win32 CRITICAL_SECTION (which SyncLock uses), it is easy to see why the decision to use Mutex must be careful weighed
However I do think they are not quite correct about SyncLock using the Win32 CRITICAL_SECTION structure (see post #13), but their tests still prove that SyncLock is much faster than Mutex.
EDIT: After reading quite a few MSDN articles and blog posts on the subject, I can confirm that SyncLock does not use the Win32 CRITICAL_SECTION as is claimed by that article mentioned above. They obviously do not understand that a SyncLock uses the Monitor class either as they conducted separate tests for SyncLock and Monitor, but like I said - their tests still show how much slower a Mutex is than SyncLock/Monitor.
Also see this graph from an MSDN article discussing how much processor time each option uses (remember that a Monitor is what SyncLock uses so its the first item in the graph that we are comparing with the last item in the graph):
Last edited by chris128; Dec 24th, 2009 at 09:13 PM.
-
Dec 25th, 2009, 10:04 AM
#26
Re: how to check if Mutex is Released
Code:
12/25/09 09:04:28.433 CPU - 1.794GHz. Stopwatch(HR) Freq. is 3,579,545
x86 Family 6 Model 13 Stepping 6 Address width - 32 Memory - 2.0GB
One - Monitor
Two - SyncLock
Number of Test(NT) = 7 Iterations Per NT(IL) = 1,048,576
Times given in ticks. 1 ms. = 10,000 ticks; 1,000 ms. = 1 second.
Ticks / Loop Fastest? One
0.0040 0.3428 0.5056 -0.1628
NT Base IL One IL Two IL Difference (One - Two)
1 4,238 351,193 529,387 -178,194
2 4,210 352,212 529,212 -177,000
3 4,211 351,027 533,413 -182,386
4 4,211 407,650 529,245 -121,595
5 4,208 350,983 528,916 -177,933
6 4,232 352,004 529,359 -177,355
7 4,208 350,819 531,909 -181,090
Average
4,216 359,412 530,205 -170,793 (-17.079 ms./IL)
12/25/09 09:04:30.217 RunMode = CTRL-F5 End Dewayne Relative Speed Test
Source Code Follows
Dim Lock As New Object
Dim x As Integer
Private Function TestCase1() As Boolean 'One
'Test One Code Follows
Monitor.Enter(Lock)
x = 1
Monitor.Exit(Lock)
'End Test One Code
Return True
End Function
'
Private Function TestCase2() As Boolean 'Two
'Test Two Code Follows
SyncLock Lock
x = 1
End SyncLock
'End Test Two Code
Return True
End Function
'
Private Sub _init()
'Code needed to get the Test to run. NOT part of the timing.
'Only called once!!!
End Sub
-
Dec 26th, 2009, 01:47 AM
#27
Thread Starter
Hyperactive Member
Re: how to check if Mutex is Released
 Originally Posted by chris128
No that is not the case, when you come out of the scope of a SyncLock block the lock will be released - it doesnt have to actually hit the End SyncLock line. Just like if you use a Using statement, you dont have to hit the End Using line for the object to be disposed, its just when you come out of the scope of that statement. I assume this behaviour is achieved by the fact that internally the SyncLock uses a Try/Catch/Finally block and releases the lock in the Finally block. You can see the same behaviour yourself if you just do something like this inside a Function:
what if i had something like this:
Code:
1: SyncLock Lock
GoTo 1
End SyncLock
does the thread leaves synclock when it hits GoTo 1 or does he enters the lock 2 times, den 3, den 4 ..
-
Dec 26th, 2009, 07:59 AM
#28
Re: how to check if Mutex is Released
I'm pretty sure it would release the lock when it jumps out of the SyncLock block. Although I think if you had a method call in there like the code below for example, then the lock would not be released until after the method had been executed and you actually reached the End SyncLock statement:
Code:
SyncLock Something
MyMethod()
End SyncLock
Sub MyMethod()
'Do some stuff...
Dim something As String = "Hello"
'I think the lock is still held at this point
End Sub
-
Dec 26th, 2009, 01:27 PM
#29
Re: how to check if Mutex is Released
try it, then you will know:
Code:
Dim lock As New Object
Dim i As Integer = 0
1: SyncLock lock
i += 1
If i < 10 Then GoTo 1
End SyncLock
Debug.WriteLine("made it")
I am not advocating the use of GoTo BTW.
-
Dec 26th, 2009, 05:40 PM
#30
Re: how to check if Mutex is Released
 Originally Posted by dbasnett
try it, then you will know:
Code:
Dim lock As New Object
Dim i As Integer = 0
1: SyncLock lock
i += 1
If i < 10 Then GoTo 1
End SyncLock
Debug.WriteLine("made it")
I am not advocating the use of GoTo BTW.
That doesnt prove anything about when the lock is released though...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|