Boost logo

Boost Users :

Subject: Re: [Boost-users] Q: N00b spinlock
From: strasser_at_[hidden]
Date: 2010-01-21 14:27:45


Zitat von Tim Blechmann <tim_at_[hidden]>:

>>> Typically you shouldn't use spinlocks, unless you are working really
>>> low level and know what you are doing, and if do_work() is very short
>>> - ie a few processor instructions.
>>
>> Well, what I am doing is setting two boolean flags.
>> This happens in an app where interactivity/responsiveness if of utmost
>> importance. I'm writing a plugin for this app.
>
> you could have a look at the proposed boost.atomic library, implementing
> c++0x-style atomics.

http://www.chaoticmind.net/~hcb/projects/boost.atomic/doc/atomic/usage_examples.html#boost_atomic.usage_examples.example_spinlock

>
>
>>> Once you are experienced with MT programming, STILL stick to simple
>>> mutex locking/unlocking.
>>
>> So why would these people use spinlocks?
>
> spinlocks are usually faster to acquire and release than mutexes, but
> require busy waiting, which may be cause an overall performance impact
> if the critical section takes some time to execute (especially, if the
> critical section itself is blocking).
> a calling thread would be suspended when waiting for a mutex to be
> locked, which could lead to some issues for certain (actually very
> little) use cases.

I have experimented with spinlocks within my library, and even if I
only use them for mutexes whose locks are usually very short-lived I
could produce usecases that end up in a performance-desaster, with 80%
CPU consumed by yield() system calls.
especially when 3 or more threads contend about a mutex, so 2 of them
are yield()ing:
if thread 1 has acquired the mutex and thread 2 and 3 are yield()ing,
it seems the scheduler constantly switches between threads 2 and 3
until they´ve used up a full time slot until thread 1 is continued and
releases the lock.

I guess there are some use cases for pure spinlocks, without
yield()ing, if you know that you have > 1 CPUs and the locks are
short-lives, but I ended up using not a single spinlock.

a combination of a Boost.Atomic atomic<> and a boost::mutex I found
useful however:

combined_mutex() : atomic_count(-1){
   this->system_mutex.lock();
}
lock(){
   if(atomic_count.fetch_add(1,...) >= 0){
     this->system_mutex.lock();
   }
}
unlock(){
   if(atomic_count.fetch_sub(1,...) > 0){
     this->system_mutex.unlock();
   }
}

for low-contention mutexes that's faster than calling pthread for every lock.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net