I think both are doing the same job,how do you decide which one to use for synchronization?
相关问题
- How to account for clock offsets in a distributed
- Why does the lock insure that the underlying monit
- how to query my database and have it be outputted
- (Java) Why is a HashSet allowed to be used synchro
- What is the name of this locking technique?
相关文章
- Java synchronized block vs concurrentHashMap vs Co
- How does the piggybacking of current thread variab
- C pthread synchronize function
- wait for promises in onbeforeunload
- Including std::lock_guard in extra scope
- Can you select which column to sync with Sync Fram
- Delete an object securely from a multi-threaded pr
- Waiting for condition in Java
Spinlock and Mutex synchronization mechanisms are very common today to be seen.
Let's think about Spinlock first.
Basically it is a busy waiting action, which means that we have to wait for a specified lock is released before we can proceed with the next action. Conceptually very simple, while implementing it is not on the case. For example: If the lock has not been released then the thread was swap-out and get into the sleep state, should do we deal with it? How to deal with synchronization locks when two threads simultaneously request access ?
Generally, the most intuitive idea is dealing with synchronization via a variable to protect the critical section. The concept of Mutex is similar, but they are still different. Focus on: CPU utilization. Spinlock consumes CPU time to wait for do the action, and therefore, we can sum up the difference between the two:
In homogeneous multi-core environments, if the time spend on critical section is small than use Spinlock, because we can reduce the context switch time. (Single-core comparison is not important, because some systems implementation Spinlock in the middle of the switch)
In Windows, using Spinlock will upgrade the thread to DISPATCH_LEVEL, which in some cases may be not allowed, so this time we had to use a Mutex (APC_LEVEL).
This is wrong. There is no wastage of cpu cycles in using spinlocks on uni processor systems, because once a process takes a spin lock , preemption is disabled , so as such, there could be no one else spinning! It's just that using it doesn't make any sense! Hence, spinlocks on Uni systems are replaced by preempt_disable at compile time by the kernel!
The Theory
In theory, when a thread tries to lock a mutex and it does not succeed, because the mutex is already locked, it will go to sleep, immediately allowing another thread to run. It will continue to sleep until being woken up, which will be the case once the mutex is being unlocked by whatever thread was holding the lock before. When a thread tries to lock a spinlock and it does not succeed, it will continuously re-try locking it, until it finally succeeds; thus it will not allow another thread to take its place (however, the operating system will forcefully switch to another thread, once the CPU runtime quantum of the current thread has been exceeded, of course).
The Problem
The problem with mutexes is that putting threads to sleep and waking them up again are both rather expensive operations, they'll need quite a lot of CPU instructions and thus also take some time. If now the mutex was only locked for a very short amount of time, the time spent in putting a thread to sleep and waking it up again might exceed the time the thread has actually slept by far and it might even exceed the time the thread would have wasted by constantly polling on a spinlock. On the other hand, polling on a spinlock will constantly waste CPU time and if the lock is held for a longer amount of time, this will waste a lot more CPU time and it would have been much better if the thread was sleeping instead.
The Solution
Using spinlocks on a single-core/single-CPU system makes usually no sense, since as long as the spinlock polling is blocking the only available CPU core, no other thread can run and since no other thread can run, the lock won't be unlocked either. IOW, a spinlock wastes only CPU time on those systems for no real benefit. If the thread was put to sleep instead, another thread could have ran at once, possibly unlocking the lock and then allowing the first thread to continue processing, once it woke up again.
On a multi-core/multi-CPU systems, with plenty of locks that are held for a very short amount of time only, the time wasted for constantly putting threads to sleep and waking them up again might decrease runtime performance noticeably. When using spinlocks instead, threads get the chance to take advantage of their full runtime quantum (always only blocking for a very short time period, but then immediately continue their work), leading to much higher processing throughput.
The Practice
Since very often programmers cannot know in advance if mutexes or spinlocks will be better (e.g. because the number of CPU cores of the target architecture is unknown), nor can operating systems know if a certain piece of code has been optimized for single-core or multi-core environments, most systems don't strictly distinguish between mutexes and spinlocks. In fact, most modern operating systems have hybrid mutexes and hybrid spinlocks. What does that actually mean?
A hybrid mutex behaves like a spinlock at first on a multi-core system. If a thread cannot lock the mutex, it won't be put to sleep immediately, since the mutex might get unlocked pretty soon, so instead the mutex will first behave exactly like a spinlock. Only if the lock has still not been obtained after a certain amount of time (or retries or any other measuring factor), the thread is really put to sleep. If the same code runs on a system with only a single core, the mutex will not spinlock, though, as, see above, that would not be beneficial.
A hybrid spinlock behaves like a normal spinlock at first, but to avoid wasting too much CPU time, it may have a back-off strategy. It will usually not put the thread to sleep (since you don't want that to happen when using a spinlock), but it may decide to stop the thread (either immediately or after a certain amount of time) and allow another thread to run, thus increasing chances that the spinlock is unlocked (a pure thread switch is usually less expensive than one that involves putting a thread to sleep and waking it up again later on, though not by far).
Summary
If in doubt, use mutexes, they are usually the better choice and most modern systems will allow them to spinlock for a very short amount of time, if this seems beneficial. Using spinlocks can sometimes improve performance, but only under certain conditions and the fact that you are in doubt rather tells me, that you are not working on any project currently where a spinlock might be beneficial. You might consider using your own "lock object", that can either use a spinlock or a mutex internally (e.g. this behavior could be configurable when creating such an object), initially use mutexes everywhere and if you think that using a spinlock somewhere might really help, give it a try and compare the results (e.g. using a profiler), but be sure to test both cases, a single-core and a multi-core system before you jump to conclusions (and possibly different operating systems, if your code will be cross-platform).
Mecki's answer pretty well nails it. However, on a single processor, using a spinlock might make sense when the task is waiting on the lock to be given by an Interrupt Service Routine. The interrupt would transfer control to the ISR, which would ready the resource for use by the waiting task. It would end by releasing the lock before giving control back to the interrupted task. The spinning task would find the spinlock available and proceed.
Continuing with Mecki's suggestion, this article pthread mutex vs pthread spinlock on Alexander Sandler's blog, Alex on Linux shows how the
spinlock
&mutexes
can be implemented to test the behavior using #ifdef.However, be sure to take the final call based on your observation, understanding as the example given is an isolated case, your project requirement, environment may be entirely different.
Please also note that on certain environments and conditions (such as running on windows on dispatch level >= DISPATCH LEVEL), you cannot use mutex but rather spinlock. On unix - same thing.
Here is equivalent question on competitor stackexchange unix site: https://unix.stackexchange.com/questions/5107/why-are-spin-locks-good-choices-in-linux-kernel-design-instead-of-something-more
Info on dispatching on windows systems: http://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/IRQL_thread.doc