Skip to content

Instantly share code, notes, and snippets.

@dadhi
Created January 8, 2020 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dadhi/1536ba40bed275f7145a4830719760dd to your computer and use it in GitHub Desktop.
Save dadhi/1536ba40bed275f7145a4830719760dd to your computer and use it in GitHub Desktop.
Better SpinWait
/*
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