A murder caused by a lock-free message queue: How to be a real programmer? (a)--ground: Cause
A murder caused by a lock-free message queue: How to be a real programmer? (b)--month: Spin lock
In the copy of the above line I stopped first, is considered to occupy a position, although I know how to write, but the feeling is still very messy.
I suddenly thought, since so tangled, so chaotic, so overwhelmed, we might as well change the angle of view. Remember the few novels I saw in high school, "The funeral of the Muslims ", the author is: Hoda (female), the story describes two occurred in different times, with different content but also staggered knot of love tragedy, one is "Jade" story, one is "month" story. The structure of the cross-section of the model, a chapter write "Jade", a chapter write "month", respectively, write the fate of two generations, novel techniques, do not have a flavor, in the language of the film, is a parallel montage. It's a good thing to use here, so it's decided!
The reason that this, originated in yesterday afternoon has not begun to write the first half of the last part, I am responsible for the reader's attitude, deliberately searched for a "spin lock" this keyword, although said not unfamiliar, but think of never through the search engine seriously studied the word, or some necessary. Search results, useful information is really not much (not to say completely useless, is basically useless), but one is still good, this also explain to me spin lock provides a good idea and theoretical basis.
This article is " spin lock instead of mutual exclusion lock practice ", this is a translation, the original article here:practice of using spinlock instead of the mutex, say a digression, yesterday I study Disruptor, the search for some important articles is also in the Concurrent Programming Network (ifeve.com) , and Disruptor updated, the article will follow the update, although not keep up with the disruptor update speed: (
To explain here, I define two space and time as: " earth " and " Moon ", Earth : Noisy and noisy, full of competition, this line mainly write things through and Free-lock (no lock programming), I occasionally will spray people; The Moon : Represents tranquility and rationality, uninhabited, and far from the earthly strife, which mainly describes spin locks (mixed spin locks, hybrid spinlocks), while the moon is also a symbol of beauty (I wanted to choose Mars, but Mars is not beautiful ...). and "Martians" don't have his meaning, you know.
All right, let's go, pineapple jackfruit!
Hello, Welcome to the moon.
Let's talk about spin locks. Why do we talk about spin locks, we're not talking about lock-free Message Queuing before? Yes, but after analyzing the q3.h, it is found that it is roughly equivalent to two spin locks in operation.
As for why it is equivalent to two spin locks, let's go back and look at the mutex (mutex locks) and spin lock (spin locks).
Mutex and Spin lock
mutexes and spin locks are important concepts in multithreaded programming . We use them to lock up some shared resources to prevent data inconsistencies that might result from concurrent access to these shared data. But where are they different? When should we use a spin lock instead of a mutual exclusion lock?
When we use mutexes , assuming that the mutex is already held by one thread (locked), the other thread fails when it tries to lock, and then goes into hibernation to wait for the other threads to run. This thread will remain dormant until the thread holding the lock releases the lock before it is awakened. So let's take a look at the spin lock , if a thread is trying to hold a spin lock , if the hold is not successful (that is, the other thread has already held the lock and is locked), the thread will always try to hold the lock (by the user-state spin), Then it does not allow other threads to run on the current core of the CPU (of course, the operating system can be forced to run on another thread by breaking or after the thread's time slice is exhausted).
problems that exist
The problem with mutexes is that both the sleep and wake of the threads are fairly expensive operations that require a lot of CPU instructions and therefore take some time. If the mutex is only locked for a short period of time, the time it takes for the thread to hibernate and wake the thread is longer than the thread's sleep, and it may even be longer than the time it rotation on the spin lock . The problem with the spin lock is that if the spin lock is held for too long, other threads trying to acquire the spin lock will always rotation the spin lock, which will be a waste of CPU execution time, and it is critical that these wasted rotation times are without effort, this time the thread sleep would be a better choice.
There is no point in using a spin lock on a single-core/single-CPU system, because it is a running thread/core that you occupy, then other threads will not run, other threads are not running, and the lock cannot be unlocked. In other words, using a spin lock on a single-core/single-CPU system is not a benefit in addition to wasting some time. At this point, if you let this thread (as thread a) hibernate, the other threads will be able to run, and then the spin lock may be unlocked, and thread A may be able to hold the lock once it has been awakened again.
On multi-core/multi-CPU systems, especially when a large number of threads hold locks for a short time, wasting a lot of time on the thread's sleep and wake-up may significantly reduce the performance of the program. With spin locks , threads can take full advantage of the time slices allocated by the system scheduler (often blocking for a short time without hibernation and then immediately continuing their work) to achieve higher processing power and throughput.
Programmers often do not know in advance which scheme is better, such as not knowing the core number of the CPU in the running environment, and not being able to estimate the duration of the locked area well. The operating system also cannot tell which directives are optimized for single-core or multi-core CPUs, so most operating systems do not strictly differentiate between mutexes and spin locks . In fact, the vast majority of operating systems now employ hybrid mutexes (hybrid mutexes) and hybrid spin locks (hybrid spinlocks). What do they mean?
Hybrid mutual-exclusion lock
Hybrid Mutex , on multicore systems, it behaves like a spin lock at first, and if a thread cannot acquire (hold) a mutex , it does not go into hibernation immediately, because the mutex can be unlocked quickly, so it behaves Spin lock . It will be switched to hibernation only after trying for a period of time (or a certain number of times, or other indicator) and cannot hold the lock. If you are running on a single-core/single-CPU system, this mechanism will not spin and should not spin (the reason is, as I said earlier, a bit of a benefit).
The best example is the critical section on Windows, which has an API called InitializeCriticalSectionAndSpinCount(Mutex, dwspincount), the function's The dwSpinCount value, Windows default recommendation is 4000 (I believe many people familiar with Windows development know), that is, spin 4,000 times, and this 4,000 times is how to spin, in the form of what kind of instructions to spin we are not sure, but it is the Earth first to try to spin The Dwspincounis still not able to hold the mutex until it actually goes into hibernation.
The hybrid spin lock , which initially behaves like a normal spin lock , has a compromise strategy in order to avoid wasting a lot of CPU time without working hard. This strategy may not switch to hibernation or as late as possible to switch to sleep, spin a period of time, spin for how long, in what form the spin will be one of the core of this type of spin lock; In addition, another more central element is that you can also decide whether to discard the execution of the current thread ( Give up immediately or wait for a time to give up, the time is determined by the spin strategy, the time slice to other threads, which increases the possibility of other thread threads unlocked spin lock (of course, thread switching causes the context to switch to another CPU core, which can cause the cache to fail, This may not be as short as a thread going into hibernation and then waking up, which is hard to weigh, but the advantage is that other threads are running, and you're going to sleep and give up the time slices, and you'll have the same problem in essence.
The author's own Ringqueue in the use of this kind of hybrid spin lock , but the hybrid spin lock is about the strategy of sleep, the strategy is different, CPU occupancy rate, the implementation efficiency are very different. For example, the Spin_mutex (i.e. Spin_lock) in the famous Intel multithreaded parallel Library uses Spin_count *= 2, which increases the number of spins by twice times, while the Sleep Strategy is switchtothread () under Windows (this is a big missing Trapped, later will say), Linux is sched_yiled () (Linux under the use of this reasonable many, but that but ..., not good enough, from the details, Windows and Linux are both pros and cons, and there are flaws, and later said, The advantage of this function, though, is that basic Linux has only one interface, rather than having too many details under windows and being vulnerable to a fatal flaw.
Another example is the Pthread pthread_spin_lock (), but this is a no- spin lock, no sleep strategy. And then there are several spin_lock,boost/smart_ptr offered in boost, and the strategy is still the right one, and the spin strategy is normal, but under Windows, sleep (0) and sleep (1) are used, Instead of using SwitchToThread (), another place, like Boost/log below, the hibernation strategy uses only Swithtothread (), without sleep (0) and sleep (1). Of course there is the SmallLocks.h in folly, spin strategy OK, but the sleep strategy uses a similar form of sleep (1).
The performance of a hybrid spin lock is directly determined by the length of time you're going to lock the resource, and the specific sleep strategy of your spin lock , which can be difficult to define, but it still gives you some relatively hard indicators, such as overall uptime and Total CPU utilization, although these two indicators are contradictory, but if your running time is short, the ratio of CPU consumption is low, it is certainly better spin lock , that is, we often say, both want to eat the cow is grass, and want to squeeze the cow is milk, the lowest efficiency can not be less than Mutual exclusion lock , which is also a reference index to test the merits of hybrid spin lock .
Well, I'm going to start sleeping here today. Actually, I studied all night last night.disruptor, so the time to write this article was delayed. When you look at the content of the above article, you will be thinking, why useSpin lockOrMutual exclusion Lock, I usedisruptorIsn't it better? Through my understanding and research, it's actually not like that,disruptorGood is good, but there are limitations, it does not circumvent the real problem of multithreaded programming, it just simplifies the problem, try to use single-threaded, or the largest program to avoid cache, bus and resource contention, try to use a single thread to handle the problem. So it is encouraged to use single-producer mode, so that effectively circumvent some of the problems of multithreading contention, so I usedisruptorTry a multi-generator, multi-consumer mode, the results of the experiment with the general spin lock is not much different, maybe more threads, but also more slowly, sodisruptorThe solution and our problem basically can be said to be two different propositions, not a dimension of things, although it seems as if there is a little resemblance. But both can learn from each other,disruptorIt also defines a lot of sleep strategies, but the actual effect is not ideal. Aboutdisruptor, it may take a bit of space later.
Ringqueue's github address is: Https://github.com/shines77/RingQueue, can also download UTF-8 encoded version: Https://github.com/shines77/RingQueue-utf8. I daresay is a nice hybrid spin lock, you can download it yourself back to see, support makefile, support Codeblocks, support Visual Studio 2008, 2010, 2013, etc., also support cmake, support windows, MinGW, Cygwin, Linux, Mac OSX and so on, of course, may not support arm, no test environment.
(not to be continued ...) Please look forward to ... ）
A murder caused by a lock-free message queue: How to be a real programmer? (b)--month: Spin lock