I have the following code
class Program
{
static SpinLock sl = new SpinLock();
public static void Foo(object arg)
{
bool r = false;
sl.Enter(ref r);
}
public static void Main(string[] args)
{
bool r = false;
sl.Enter(ref r);
ThreadPool.QueueUserWorkItem(Foo);
Thread.Sleep(5000);
sl.Exit();
Thread.Sleep(5000);
}
}
When I execute it, I see ~0% of the CPU load throughout the whole program run. I was expecting to see some CPU burn due to spinning inside the sl.Enter()
call, but this is not the case.
According to SpinLock source, it uses SpinWait
under the hood, which in turn actually calls Thread.Sleep(1)
at some point.
Does that mean that both SpinLock
and SpinWait
aren't really "spinners", but instead still resort to the OS scheduler to yield some CPU shares?
EDIT
The question can be reformulated in the following way:
Using busy-looping ensures that the time between one thread releasing a lock and another thread acquiring it is minimal. Can I rely on SpinLock
/SpinWait
in this regard? From what I can tell, the answer is no, because it does Sleep
for at least 1 microsecond, and the lock might be freed somewhere during this time.
CodePudding user response:
Regarding your edited question, yes busy spinning will give you the lowest latency of communication between the threads but you will pay for it by burning CPU time.
On the other hand you can use SpinWait
which is less aggressive or you can code something in between such as this.
It comes down to a trade-off on how much you value latency and how many cores you have to spare.