[ACCEPTED]-What's the purpose of Thread.SpinWait method?-multithreading

Accepted answer
Score: 109

no. Its used as a replacement for very short-term 38 sleep calls.

When you do multi-threaded 37 locking, if the resource you're attempting 36 to acquire is already locked, you typically 35 go to sleep and wait for it to become free. When 34 you do this, you give up the rest of the 33 time that you were allocated by the scheduler 32 to use the processor so someone else can 31 have a go. Normally this is fine, especially 30 for long waits, like waiting for IO, loads 29 of other processes can run on the CPU while 28 you're waiting for the disk spindle to rotate.

However, sometimes, you're 27 waiting for a tiny amount of time. In these 26 cases, you would normally give up your remaining 25 time anyway and wait for all the other threads 24 to do their thing before getting another 23 go.. so you can cheat, instead of waiting, you 22 sit there continually polling in a 'are 21 we nearly there yet?' way. If the lock is 20 only held for a fraction of your remaining 19 time, this becomes a very effective means 18 of waiting, its also very efficient as the 17 scheduler doesn't have to get involved in 16 rearranging all the other threads to use 15 the time you give up if you waited normally.

Obviously, if 14 you spin every time you want a lock, you're 13 not going to be very popular, your app will 12 become sluggish and use 100% CPU, but in 11 very small doses, at the right time, it 10 makes the app more responsive.

If you're 9 now thinking 'when should I use it?', that's 8 a tricky call to make - if you have a resource 7 that is very often locked and unlocked very 6 quickly, then a spinlock around that instead 5 of a wait is a good idea (and then test 4 your app for performance), if you try spinning 3 for a short time, and then fall back to 2 a normal wait, that's a reasonable way too. But 1 generally, you will never need to use it.

Score: 77

The purpose is to do a "cheap" wait if you 14 believe that the condition you're waiting 13 for will come true very, very soon. Normally if you're 12 waiting for something, you let the thread 11 go to sleep and the processor/OS will context 10 switch to another thread. Context switches 9 aren't particularly cheap, so if you have 8 advanced knowledge of the situation and 7 believe it's cheaper to wait than to context 6 switch, you spin wait.

My advice: if you 5 need to ask, you don't need to use it. (I've 4 never wanted it myself.) Basically it's 3 one of those things which is really useful 2 in a very few situations, but most people 1 should leave well alone.

Score: 15

As a side note, Microsoft have gotten rid 3 of the thread dispatcher spinlock mechanism 2 from Windows 7, since it didn't scale well 1 for multicore CPU's. Have a look at this:

Score: 6

As far as I'm concerned (and I'm happy for 10 corrections!), the only use of spin waits 9 is when implementing a locking or inter-thread-callback 8 mechanism. And neither should be done manually 7 (usually), since they already exist.

When 6 you've locked a resource and another thread 5 requests synchronized access to it, it basically 4 has to wait for the first thread to finish 3 using it. This waiting can be done by simply 2 spinning in a loop (or otherwise sleeping 1 + context switching as mentioned by Jon).

Score: 0

If you need a precise sleep time you cannot 7 use Thread.Sleep() because it is very unprecise (± 25 6 ms depending on CPU load) because Windows 5 is a multitasking operating system. I use 4 the following code for timing relevant and 3 short sleep intervals of a few milliseconds 2 only.

// IMPORTANT:
// Use this only for very short sleep intervals. 
// One CPU core will run with 100% load during this interval.
public static void SleepPrecise(int s32_Interval) // in ms
{
    if (s32_Interval <= 0)
        return;

    // System.Diagnostics.Stopwatch uses the performance counter in the processor 
    // which has a precision of micro seconds or even nano seconds.
    Stopwatch i_Watch = new Stopwatch();
    i_Watch.Start();

    while (i_Watch.ElapsedMilliseconds < s32_Interval)
    {
        // SpinWait(80000) --> 1 ms on a 3.6 GHz AMD Radeon processor
        Thread.SpinWait(5000);
    }
}

If you need extremely high timing precision 1 you can additionally:

Thread.CurrentThread.Priority = ThreadPriority.Highest;
try
{
   .... execute your timing relevant code
}
finally
{
    Thread.CurrentThread.Priority = ThreadPriority.Normal;
}

More Related questions