Interlocked vs Mutex efficiency

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have the following two code blocks which should only have 3 threads at the
most calling the function and collisions are very unlikely because all 3
threads should rarely be calling this function at the *exact* same time. I
am wondering which code block I should use for optimum efficiency and speed
given the conditions. I've hear that the Interlocked class is much more
efficient than a Mutex and should be used when it makes sense to, however I
don't know if this is true for sure. I've heard that the Mutex will cause
(or is it *may* cause) a context switch and that the Interlocked class does
not. Which code block will be fastest and why?

Thanks,


// **** Code block 1*****

bool sendMsgToIFac = false;

do
{
int lastSeqNum = this.lastSeqNumReceived;
int newSeqNum;

if(
(seqNum != (lastSeqNum + 1))
&& !(seqNum == 0 && (lastSeqNum == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num

newSeqNum = lastSeqNum;
sendMsgToIFac = false;
}
else
{
newSeqNum = lastSeqNum + 1;
if(newSeqNum > this.maxSeqNums - 1)
newSeqNum = 0;
sendMsgToIFac = true;
}

} while(lastSeqNum != Interlocked.CompareExchange(ref lastSeqNumReceived,
newSeqNum, lastSeqNum));


//**** OR ******* Code block 2

bool sendMsgToIFac = false;
this.receiveSeqNumMutex.WaitOne();
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
this.receiveSeqNumMutex.ReleaseMutex();




Also, from the following article:
http://msdn.microsoft.com/library/d...enref/html/cpconThreadingDesignGuidelines.asp

"
Be aware of issues with the lock statement (SyncLock in Visual Basic). It is
tempting to use the lock statement to solve all threading problems. However,
the System.Threading.Interlocked Class is superior for updates that must be
atomic. It executes a single lock prefix if there is no contention. In a code
review, you should watch out for instances like the one shown in the
following example.
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?


Thanks,
 
I do C#, so not aware of particular VB issues, but generally you would almost
always choose a Monitor/Lock over a mutext unless you need a named or cross
process mutext for some reason. If all you need to do is increment a counter
that you won't be in contention too often I would think Interlocked methods
would be the way to go. Also never do lock(this) as in that example code to
avoid potential deadlocks, instead allocate and internal object and lock on
that instead of lock(this).

Interlocked methods use a processor instruction to increment or exchange
values atomically. They do this by locking the cache for that area of memory
for the duration of the instruction so that no other CPU could get it and
that instruction is atomic on the single CPU so will not be interrupted. So
in theory depending on usage (not using it all over the place) it could be
very fast, but if you use it all over the place you are locking the cache
memory for that instruction length so another processor could not get it. On
single processor since it executes atomically I would presume it is not as
big of an issue (since everything will be multicore soon though think
multiprocessor).



Chris Tanger said:
I have the following two code blocks which should only have 3 threads at the
most calling the function and collisions are very unlikely because all 3
threads should rarely be calling this function at the *exact* same time. I
am wondering which code block I should use for optimum efficiency and speed
given the conditions. I've hear that the Interlocked class is much more
efficient than a Mutex and should be used when it makes sense to, however I
don't know if this is true for sure. I've heard that the Mutex will cause
(or is it *may* cause) a context switch and that the Interlocked class does
not. Which code block will be fastest and why?

Thanks,


// **** Code block 1*****

bool sendMsgToIFac = false;

do
{
int lastSeqNum = this.lastSeqNumReceived;
int newSeqNum;

if(
(seqNum != (lastSeqNum + 1))
&& !(seqNum == 0 && (lastSeqNum == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num

newSeqNum = lastSeqNum;
sendMsgToIFac = false;
}
else
{
newSeqNum = lastSeqNum + 1;
if(newSeqNum > this.maxSeqNums - 1)
newSeqNum = 0;
sendMsgToIFac = true;
}

} while(lastSeqNum != Interlocked.CompareExchange(ref lastSeqNumReceived,
newSeqNum, lastSeqNum));


//**** OR ******* Code block 2

bool sendMsgToIFac = false;
this.receiveSeqNumMutex.WaitOne();
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
this.receiveSeqNumMutex.ReleaseMutex();




Also, from the following article:
http://msdn.microsoft.com/library/d...enref/html/cpconThreadingDesignGuidelines.asp

"
Be aware of issues with the lock statement (SyncLock in Visual Basic). It is
tempting to use the lock statement to solve all threading problems. However,
the System.Threading.Interlocked Class is superior for updates that must be
atomic. It executes a single lock prefix if there is no contention. In a code
review, you should watch out for instances like the one shown in the
following example.
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?


Thanks,
 
If you only have one CPU, 3 threads can not access at same time *exactly
anyway as only one thread can run at one time. If thread1 gets the lock and
OS switches to thread2 it could, however, block on the lock. Just use
Lock() {} (i.e. Monitor). Best overall in performance and ease of use and
getting it correct. Using things like Interlocked.CompareExchange for sync
is hard to get right and probably not worth the effort.

--
William Stacey, MVP
http://mvp.support.microsoft.com

Chris Tanger said:
I have the following two code blocks which should only have 3 threads at the
most calling the function and collisions are very unlikely because all 3
threads should rarely be calling this function at the *exact* same time. I
am wondering which code block I should use for optimum efficiency and speed
given the conditions. I've hear that the Interlocked class is much more
efficient than a Mutex and should be used when it makes sense to, however I
don't know if this is true for sure. I've heard that the Mutex will cause
(or is it *may* cause) a context switch and that the Interlocked class does
not. Which code block will be fastest and why?

Thanks,


// **** Code block 1*****

bool sendMsgToIFac = false;

do
{
int lastSeqNum = this.lastSeqNumReceived;
int newSeqNum;

if(
(seqNum != (lastSeqNum + 1))
&& !(seqNum == 0 && (lastSeqNum == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num

newSeqNum = lastSeqNum;
sendMsgToIFac = false;
}
else
{
newSeqNum = lastSeqNum + 1;
if(newSeqNum > this.maxSeqNums - 1)
newSeqNum = 0;
sendMsgToIFac = true;
}

} while(lastSeqNum != Interlocked.CompareExchange(ref lastSeqNumReceived,
newSeqNum, lastSeqNum));


//**** OR ******* Code block 2

bool sendMsgToIFac = false;
this.receiveSeqNumMutex.WaitOne();
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
this.receiveSeqNumMutex.ReleaseMutex();




Also, from the following article:
http://msdn.microsoft.com/library/d...enref/html/cpconThreadingDesignGuidelines.asp

"
Be aware of issues with the lock statement (SyncLock in Visual Basic). It is
tempting to use the lock statement to solve all threading problems. However,
the System.Threading.Interlocked Class is superior for updates that must be
atomic. It executes a single lock prefix if there is no contention. In a code
review, you should watch out for instances like the one shown in the
following example.
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?


Thanks,
 
.. . .
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will
improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?

This bit of advice fails utterly to understand the scale of the performance
difference between these two approaches, and risks using InterlockedXXX when
scope-based locking is more appropriate. For most programmers it's not
worth keeping track of multiple synchronization objects and when to use each
one. Just use lock/SyncLock all the time.

Interlocked.Increment is implemented in the processor, and is faster. But
lock/SyncLock is a lightweight user-mode lock, so the performance difference
between them is usually insignificant. Mutexes are kernel-based, and so are
slower. So they should only be used when you need the extra functionality
of a Mutex (name, cross-process synchronization, abandoned waits).

The important thing to understand is the scope of the lock required to make
the code correct. In your example, the two methods of syncronization were
not equivilent. The mutex protected a whole block, the Interlocked method
only protected one statement. This is the shortcoming of the Interlocked
methods: they only syncronize a single atomic operation on a variable.

The exaple posted should use lock, not a Mutex or an Interlocked Function.
A lock() scope will automatically unlock in case of an exception, and it
makes it very obvious what operations are being synchronized.


bool sendMsgToIFac = false;
lock(this)
{
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
}

David
 
I would mostly agree (Except there will be multicore processors soon).
Definately for ease of use and getting it right the
lock(myinternalobjectlock) construct is much easier for the majority of
people to use and get right. InterlockedCompareExchange is much tougher to
get right in that scenario. If done right it can be faster, but if done
wrong it either isn't or utterly fails.

William Stacey said:
If you only have one CPU, 3 threads can not access at same time *exactly
anyway as only one thread can run at one time. If thread1 gets the lock and
OS switches to thread2 it could, however, block on the lock. Just use
Lock() {} (i.e. Monitor). Best overall in performance and ease of use and
getting it correct. Using things like Interlocked.CompareExchange for sync
is hard to get right and probably not worth the effort.

--
William Stacey, MVP
http://mvp.support.microsoft.com

Chris Tanger said:
I have the following two code blocks which should only have 3 threads at the
most calling the function and collisions are very unlikely because all 3
threads should rarely be calling this function at the *exact* same time. I
am wondering which code block I should use for optimum efficiency and speed
given the conditions. I've hear that the Interlocked class is much more
efficient than a Mutex and should be used when it makes sense to, however I
don't know if this is true for sure. I've heard that the Mutex will cause
(or is it *may* cause) a context switch and that the Interlocked class does
not. Which code block will be fastest and why?

Thanks,


// **** Code block 1*****

bool sendMsgToIFac = false;

do
{
int lastSeqNum = this.lastSeqNumReceived;
int newSeqNum;

if(
(seqNum != (lastSeqNum + 1))
&& !(seqNum == 0 && (lastSeqNum == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num

newSeqNum = lastSeqNum;
sendMsgToIFac = false;
}
else
{
newSeqNum = lastSeqNum + 1;
if(newSeqNum > this.maxSeqNums - 1)
newSeqNum = 0;
sendMsgToIFac = true;
}

} while(lastSeqNum != Interlocked.CompareExchange(ref lastSeqNumReceived,
newSeqNum, lastSeqNum));


//**** OR ******* Code block 2

bool sendMsgToIFac = false;
this.receiveSeqNumMutex.WaitOne();
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
this.receiveSeqNumMutex.ReleaseMutex();




Also, from the following article:
http://msdn.microsoft.com/library/d...enref/html/cpconThreadingDesignGuidelines.asp

"
Be aware of issues with the lock statement (SyncLock in Visual Basic). It is
tempting to use the lock statement to solve all threading problems. However,
the System.Threading.Interlocked Class is superior for updates that must be
atomic. It executes a single lock prefix if there is no contention. In a code
review, you should watch out for instances like the one shown in the
following example.
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?


Thanks,
 
A quick test of 1 million iterations of lock(object) { increment++} vs
Interlocked.Increment gave a result on my machine 60ms for lock and 20ms for
Interlocked. A 3 times improvement in performance. As I and others have
stated more complex usages must be done with great care as exchanges are easy
to mess up and if there is too much contextion and used in too many places it
is possible to reduce efficiency

Chris Tanger said:
I have the following two code blocks which should only have 3 threads at the
most calling the function and collisions are very unlikely because all 3
threads should rarely be calling this function at the *exact* same time. I
am wondering which code block I should use for optimum efficiency and speed
given the conditions. I've hear that the Interlocked class is much more
efficient than a Mutex and should be used when it makes sense to, however I
don't know if this is true for sure. I've heard that the Mutex will cause
(or is it *may* cause) a context switch and that the Interlocked class does
not. Which code block will be fastest and why?

Thanks,


// **** Code block 1*****

bool sendMsgToIFac = false;

do
{
int lastSeqNum = this.lastSeqNumReceived;
int newSeqNum;

if(
(seqNum != (lastSeqNum + 1))
&& !(seqNum == 0 && (lastSeqNum == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num

newSeqNum = lastSeqNum;
sendMsgToIFac = false;
}
else
{
newSeqNum = lastSeqNum + 1;
if(newSeqNum > this.maxSeqNums - 1)
newSeqNum = 0;
sendMsgToIFac = true;
}

} while(lastSeqNum != Interlocked.CompareExchange(ref lastSeqNumReceived,
newSeqNum, lastSeqNum));


//**** OR ******* Code block 2

bool sendMsgToIFac = false;
this.receiveSeqNumMutex.WaitOne();
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
this.receiveSeqNumMutex.ReleaseMutex();




Also, from the following article:
http://msdn.microsoft.com/library/d...enref/html/cpconThreadingDesignGuidelines.asp

"
Be aware of issues with the lock statement (SyncLock in Visual Basic). It is
tempting to use the lock statement to solve all threading problems. However,
the System.Threading.Interlocked Class is superior for updates that must be
atomic. It executes a single lock prefix if there is no contention. In a code
review, you should watch out for instances like the one shown in the
following example.
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?


Thanks,
 
I think I can get the Interlocked right, it isn't that complicated. For
the moment I will use lock though to keep things simple. I AM interested in
performance and scalabilty as I am writing a server program that services
about 1000 clients and it does run on dual processor servers.

Thanks for the help.

-Chris

WXS said:
I would mostly agree (Except there will be multicore processors soon).
Definately for ease of use and getting it right the
lock(myinternalobjectlock) construct is much easier for the majority of
people to use and get right. InterlockedCompareExchange is much tougher to
get right in that scenario. If done right it can be faster, but if done
wrong it either isn't or utterly fails.

William Stacey said:
If you only have one CPU, 3 threads can not access at same time *exactly
anyway as only one thread can run at one time. If thread1 gets the lock and
OS switches to thread2 it could, however, block on the lock. Just use
Lock() {} (i.e. Monitor). Best overall in performance and ease of use and
getting it correct. Using things like Interlocked.CompareExchange for sync
is hard to get right and probably not worth the effort.

--
William Stacey, MVP
http://mvp.support.microsoft.com

Chris Tanger said:
I have the following two code blocks which should only have 3 threads at the
most calling the function and collisions are very unlikely because all 3
threads should rarely be calling this function at the *exact* same time. I
am wondering which code block I should use for optimum efficiency and speed
given the conditions. I've hear that the Interlocked class is much more
efficient than a Mutex and should be used when it makes sense to, however I
don't know if this is true for sure. I've heard that the Mutex will cause
(or is it *may* cause) a context switch and that the Interlocked class does
not. Which code block will be fastest and why?

Thanks,


// **** Code block 1*****

bool sendMsgToIFac = false;

do
{
int lastSeqNum = this.lastSeqNumReceived;
int newSeqNum;

if(
(seqNum != (lastSeqNum + 1))
&& !(seqNum == 0 && (lastSeqNum == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num

newSeqNum = lastSeqNum;
sendMsgToIFac = false;
}
else
{
newSeqNum = lastSeqNum + 1;
if(newSeqNum > this.maxSeqNums - 1)
newSeqNum = 0;
sendMsgToIFac = true;
}

} while(lastSeqNum != Interlocked.CompareExchange(ref lastSeqNumReceived,
newSeqNum, lastSeqNum));


//**** OR ******* Code block 2

bool sendMsgToIFac = false;
this.receiveSeqNumMutex.WaitOne();
if(
(seqNum != (this.lastSeqNumReceived + 1))
&& !(seqNum == 0 && (this.lastSeqNumReceived == (this.maxSeqNums - 1)))
)
{
// Ignore message, unexpected seq num
sendMsgToIFac = false;
}
else
{
this.lastSeqNumReceived++;
if(this.lastSeqNumReceived > this.maxSeqNums - 1)
this.lastSeqNumReceived = 0;
sendMsgToIFac = true;
}
this.receiveSeqNumMutex.ReleaseMutex();




Also, from the following article:
http://msdn.microsoft.com/library/d...enref/html/cpconThreadingDesignGuidelines.asp

"
Be aware of issues with the lock statement (SyncLock in Visual Basic). It is
tempting to use the lock statement to solve all threading problems. However,
the System.Threading.Interlocked Class is superior for updates that must be
atomic. It executes a single lock prefix if there is no contention. In a code
review, you should watch out for instances like the one shown in the
following example.
[Visual Basic]
SyncLock Me
myField += 1
End SyncLock
[C#]
lock(this)
{
myField++;
}
If you replace the previous example with the following one, you will improve
performance.

[Visual Basic]
System.Threading.Interlocked.Increment(myField)
[C#]
System.Threading.Interlocked.Increment(myField);
"

Why is the Interlocked version more efficient than the lock version?


Thanks,
 
Back
Top