41

Is spinlock and polling the same thing?

Wikipedia:

a spinlock is a lock which causes a thread trying to acquire it to simply wait in a loop ("spin") while repeatedly checking if the lock is available

This sounds awfully lot like:

while(!ready);

I was taught to avoid polling whenever possible as it was throughly sub-optimal. So, is spinlock a fancy name for bad old polling? How is a spinlock different from polling?

85

Polling refers to repeatedly checking whether a resource (any kind of resource) is ready.

A spinlock is when the resource you are polling is a lock.

Note that polling is not bad. In particular, polling is efficient when there is usually data ready when you poll. Polling is only inefficient if you do it without then getting any data in return.

On the other hand, interrupts are inefficient if there is so much data that you constantly get interrupted. They are efficient if data arrives rarely enough that you can actually get some useful work done before getting interrupted.

I can give you a real-life example from my own experience: 15 years ago, I had my email program set up to interrupt me every time a new email comes in. Which happened once or twice a week. Constantly checking my inbox would have been a colossal waste of time.

Nowadays, I have all notifications turned off. I know that whenever I look into my inbox, there'll be new emails there. Polling is much more efficient now.

Spinlocks are efficient when a) the likelihood that the lock is taken is low, and b) if the lock is taken, it will only be held for a short time. In other words: it is efficient for mostly uncontended fine-grained locks, but inefficient for highly contended coarse-grained locks.

(And of course, spinlocks only work when there is true parallelism, otherwise the other thread won't have a chance to release the lock. I guess that's kind of obvious, but I wanted to state it anyway.)

  • 5
    Spinlocks can be perfectly sensible in a cooperatively multitasked environment. You just have to make sure you're yielding control in the loop. – Kevin Nov 7 '15 at 0:15
  • 4
    Great example with emails. Reminds me of you always have email... – Petr Pudlák Nov 7 '15 at 20:01
  • 2
    @Kevin: I have a very puristic idea of a spinlock, literally a lock that just spins in an empty loop. (atomically_do { while (lock.is_locked?); lock.acquire! }) If it yields, it's not an empty loop and thus not a spinlock in that puristic view :-D But of course some hybridization with other types of locks or relaxations/additions to the platonic ideal make perfect sense in the real world. – Jörg W Mittag Nov 8 '15 at 16:25
  • 3
    @bubakazouba: A spinlock works by literally "spinning" in an empty loop and checking "Is the lock released yet? Is the lock released yet? Is the lock released yet? Is the lock released yet? Is the lock released yet?" over and over again. If there is no parallelism, then there is no other thread running at the same time that could release the lock, so you effectively have an endless loop! See the comment directly above yours. – Jörg W Mittag Nov 9 '15 at 20:38
  • 1
    @kasperd: You can still see cooperative multitasking in event-driven server software like nginx. In that case, there is one thread and no locking, which means you only get to exploit one core. To the best of my knowledge, there are literally no real-world examples of true multicore cooperative multitasking. Such a system would be stupid, since you would get all the downsides of cooperative multitasking without the upside of no locks. – Kevin Dec 27 '15 at 21:02
10

A spinlock is a type of lock, specifically, one achieved via polling.

Polling is a method of checking the status of something (by asking for the status, as opposed to waiting to be told the status).

Not all polling is a spinlock, for example, polling the status of keyboard keys.


Also, polling isn't inherently bad. Very short periods of polling can avoid expensive context shifts that use of interrupts would require, not to mention that polling can sometimes be simpler to implement and thus easier to maintain, especially at lower levels. As usual, absolutes are a terrible thing, and you should use the method that gives the appropriate performance/complexity trade off for your needs as you have measured them, rather than blindly using or discarding options.

5

Spinlock is different from polling because it only occurs for a very short period of time, on the order of a few milliseconds or less. Polling can go on indefinitely.

In parallel programming, a brief episode of spinning is often preferable to blocking, as it avoids the cost of context switching and kernel transitions.

Further Reading
SpinLock and SpinWait in C#
Spinlocks and Read-Write Locks in C

  • I think you meant to say microseconds. For a lock that lasts an entire millisecond we should use a lock implementation that makes a kernel call on contention. – Peter Nov 9 '15 at 10:11
  • @Peter Perhaps that's what Albahari meant. That's what his text says. – Robert Harvey Nov 9 '15 at 15:43
4

The difference is that a spinlock is (hopefully) only used in situations where it is appropriate, and in these situations it is very efficient.

You use a spinlock if you expect that a resource will only be locked for a very short time - for example if a lock is only used to update a variable. The spinlock polls the lock at maximum speed, but hopefully for less than microseconds. A normal mutex would require on OS call. IF the lock is only held for a tiny amount of time, then the spinlock only uses a tiny amount of CPU time, while the OS call will take longer. But if this expectation is wrong, then the spinlock is very inefficient - it will use 100% CPU time on one CPU, while the normal mutex only takes the time for entering the OS and returning.

Sometimes both are combined; you run the spin lock for a short time and switch to a different strategy if the spinlock doesn't work.

2

Excessive polling is something you should not do because it wastes system resources. It follows that polling is fine if it doesn't waste system resources.

For example excessive polling will get CPU load to 100% in cases where the actual work would only result in a 2% load.

Polling can be used for other things than while(!ready). For example it means checking regularly if the user pressed a key. A sane implementation will check at most once every 15 milliseconds, so it's one check every ~20 million clock cycles. That kind of polling is great, because it doesn't waste system resources.

A SpinLock is not a special case. If we have a SpinLock and one thread enters the lock, and another has to wait, the SpinLock is the wrong choice if and only if the waiting thread wastes system resources. The waiting thread will waste system resources if and only if it has to wait for a significant amount of time before it can acquire the lock.

Therefore, using a SpinLock to protect a anything that requires a couple thousand clock cycles or more before it unlocks again (e.g. compiling and executing a piece of javascript on the fly) is bad, exactly for the reason you stated. But using a SpinLock to protect something that completes quickly, like accessing a properly implemented hash map is fine because the waiting thread will only spin 2 or 3 times and therefore doesn't waste system resources.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.