Click here to Skip to main content
Licence 
First Posted 21 May 2002
Views 126,892
Bookmarked 11 times

Spin Lock

By | 16 Jun 2002 | Article
Efficient synchronised access to shared resources

Introduction

Spin locks are a very simple and, in the right context, efficient method of synchronising access to shared resources. The overhead of using Critical Sections or Events for resource acquision is relatively large, but in contrast, a spin lock is very quick.

Algorithm

Predictably, the algorithm for a spin lock is very simple. Each thread will instantiate a CSpinLock with a shared lock variable. When a shared resource is required, the threads call lock() and when the resource has been finished with, call unlock().

lock() will cause the thread to loop until the resource is available. The availability of the resource is defined by the value of shared variable. If the value of this variable is zero, then the resource is available, otherwise it is in use by another thread. When the resource is locked, the shared variable holds the value 0x6b636f6c. This will read "lock" if it is cast to a char *

Implementation

The CSpinLock class implements a spin lock synchronisation object.

Methods

explicit CSpinLock(long *plock = 0)
This is the only class constructor. It passes a pointer to a shared variable to hold the lock value. This parameter can be omitted, in which case an internal class lock variable will be used.

~CSpinLock()
Class destructor. Simply asserts that the object that is going out of scope does not hold the lock.

void lock(void) const
Call this method to acquire a lock to the shared resource.

void unlock(void) const
Call this method to release the lock to the shared resource.

bool has_lock(void) const
Returns true/false to signify if the object currently holds the lock

Usage

The only decision to be made in using this class is in how the lock variable is used. The easiest use is to omit the ctor parameter and let the class handle this itself. Each resource that is to be shared can be synchronised using a different template parameter value. Each thread can independently instantiate a CSpinLock object and the class implementation will ensure that the resource is synchronised correctly.

Contact

Web Site: http://homepage.virgin.net/cdm.henderson
e-mail: cdm.henderson@virgin.net

Revision History

17 Jun 2002 - Initial Revision

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Craig Henderson

Other
Centrix Software
United Kingdom United Kingdom

Member

Follow on Twitter Follow on Twitter
Craig graduated with a B.SC. Honours in Computing for Real Time Systems from the University of the West of England, Bristol in 1995 after completing an HND in Computing in 1993.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralUse Sleep( 0 ) Pinmemberajohnson12314:20 20 Mar '04  
GeneralRe: Use Sleep( 0 ) Pinmemberbkausbk8:48 11 Apr '04  
QuestionDid you test the code before posting? PinmemberAnonymous18:20 17 Jun '02  
AnswerRe: Did you test the code before posting? PinmemberAnonymous18:25 17 Jun '02  
AnswerRe: Did you test the code before posting? PinmemberCraig Henderson0:54 21 Jun '02  
GeneralBug in has_lock() PinmemberEric Kenslow11:25 17 Jun '02  
GeneralRe: Bug in has_lock() PinmemberCraig Henderson0:56 21 Jun '02  
GeneralA small almost irrelevant point PinmemberNish - Native CPian1:40 23 May '02  
GeneralRe: A small almost irrelevant point PinmemberCraig Henderson2:44 23 May '02  
GeneralRe: A small almost irrelevant point PinmemberJoao Vaz11:19 23 May '02  
GeneralRe: A small almost irrelevant point PinmemberNish - Native CPian15:39 23 May '02  
GeneralAnother alternative for Spin Lock PinmemberMaxime Labelle1:28 23 May '02  
GeneralNot a bad attempt but ... PinmemberJoao Vaz0:52 23 May '02  
You should use FreeLibrary within your destructor , this is necessary in at least on Win95 and Win98.
Besides ,you could be used the Sleep(0) instruction to abdicate thread time without SwitchToThread ... You have another drawback ,that is as long as the spinlock is owned other waiting threads are spinning and using valuable CPU time doing nothing useful.
 
A more complex , but superior aproach would be creating a waiters variable , a event object , a own avariable and a n spin retries , this number is tricky, because it should be less than it takes to do a full thread or process context switch and is should be long enough to prevent the situation when the spinlock is going to be released within a few microseconds.
 
Steps:
 

Requesting the spinlock.

 
First the lock function should start spinning n spin counts, this number is tricky to choose , because the time spent spinning should be less than it takes to do a full thread/process/context-switch and is should be long enough to prevent the wait if the spinlock is going to be released within a few microseconds.
 
something like this :
 
for(unsigned spin=0; spin<spin_retries; spin++) {
    if(InterlockedExchange(m_plock,1)==0)
      return;
  }
 
then
 

the waiters variable is incremented (must be done with InterlockedExchange() since other threads may be modifying it at the same time). Then it the spinlock tries to obtain the spinlock with a InterlockedExchange(). If that succeeds waiters is decremented and the function returns. If it does not succeed it blocks on the event , then resets the event and goes back to trying to obtain the spinlock.
 
something like this:
 
 
InterlockedIncrement(&waiters);
  for(; ; ) {
    if(InterlockedExchange(m_pLock,1)==0) {
      InterlockedDecrement(&waiters);
      return;
    }
    WaitSingleObject(hEvent, ...);
    ResetEvent(hEvent);
  }
 
 
the complete picture of the body of lock function could be something like this
 
for(unsigned spin=0 ; spin<spin_retries; spin++) {
    if(InterlockedExchange(m_plock,1)==0)
      return;
}
InterlockedIncrement(&waiters);
  for(; ; ) {
    if(InterlockedExchange(m_pLock,1)==0) {
      InterlockedDecrement(&waiters);
      return;
    }
    WaitSingleObject(hEvent, ...);
    ResetEvent(hEvent);
  }
 
 

Releasing the spinlock.

First ownership is released by setting owned to 0. Then if there are any waiters (they may be blocked on the manual reset event ) the event is posted to wake them up.
 
the unlock function could be something like this:
 
owned = 0;
if(waiters!=0)
    SetEvent(hEvent);
 
 

This kind of implementation has the following advantages:
 
-> requesting an unowned spinlock takes only a few instructions
-> requesting an owned spinlock may not need an expensive API call
-> releasing a spinlock that no one is waiting for is fast
-> valuable CPU time is not spent spinning forever
 
Disadvantages : at least one, this provoques a deadlock, concerning nested ownership, aka , requesting a spinlock that you already have causes ... deadlock ... this sincerily is to hard for me to resolve since, I don't actually known that much about Multithreading , and this kind of stuff is hard as is , so I currently don't know how to solve it efficiently Frown | :-(
 
If someone knows I much like to know ...
 

 

 

 

 
Cheers,
Joao Vaz
A person who is nice to you, but rude to the waiter, is not a nice person - Natalie Portman (Padme/Amidala of Star Wars)
GeneralRe: Not a bad attempt but ... PinmemberWes Jones8:06 23 May '02  
GeneralRe: Not a bad attempt but ... PinmemberMatt Gullett8:31 23 May '02  
GeneralRe: Not a bad attempt but ... PinmemberJoao Vaz11:09 23 May '02  
GeneralCritical sections etc. + Metered Sections PinmemberNeville Franks12:38 23 May '02  
GeneralRe: Critical sections etc. + Metered Sections PinmemberMatt Gullett12:43 23 May '02  
GeneralRe: Critical sections etc. + Metered Sections PinmemberNeville Franks12:53 23 May '02  
GeneralRe: Critical sections etc. + Metered Sections PinmemberMatt Gullett13:04 23 May '02  
GeneralRe: Critical sections etc. + Metered Sections PinmemberJoao Vaz19:57 23 May '02  
GeneralRe: Not a bad attempt but ... PinmemberTim Smith8:26 23 May '02  
GeneralRe: Not a bad attempt but ... PinmemberJoao Vaz10:44 23 May '02  
GeneralRe: Not a bad attempt but ... PinmemberJoao Vaz11:29 23 May '02  
GeneralRe: Not a bad attempt but ... PinmemberTim Smith12:59 23 May '02  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120529.1 | Last Updated 17 Jun 2002
Article Copyright 2002 by Craig Henderson
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid