Created
January 8, 2020 11:07
-
-
Save dadhi/1536ba40bed275f7145a4830719760dd to your computer and use it in GitHub Desktop.
Better SpinWait
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
sources: | |
- http://www.adammil.net/blog/v111_Creating_High-Performance_Locks_and_Lock-free_Code_for_NET_.html | |
- http://badamczewski.blogspot.com/2012/08/lock-free-and-spinwait-msdn-example.html | |
A better spin lock: | |
The result is a spin lock that's quite fast — about twice as fast as locking with a Monitor (or the C# lock statement). | |
(It can be further sped up slightly by breaking the Enter method into two methods: Enter, | |
which does `if(Interlocked.CompareExchange(ref state, 1, 0) != 0) EnterSpin();` | |
and `EnterSpin`, a private method that uses a do/while loop to perform the spin. | |
This allows the compiler to inline the Enter method, and it's effective because much of the time the lock should not need to spin.) Spin locks are very effective when the lock will only be held for a very short length of time, but otherwise they are likely to consume CPU time unnecessarily. | |
*/ | |
public void Enter() | |
{ | |
int spinCount = 0; | |
while(Interlocked.CompareExchange(ref state, 1, 0) != 0) SpinWait(spinCount++); | |
} | |
static void SpinWait(int spinCount) | |
{ | |
if(spinCount < 10 && MultiProcessor) Thread.SpinWait(20*(spinCount+1)); | |
else if(spinCount < 15) Thread.Sleep(0); // or use Thread.Yield() in .NET 4 | |
else Thread.Sleep(1); | |
} | |
static readonly bool MultiProcessor = Environment.ProcessorCount > 1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment