Created
July 1, 2012 09:31
-
-
Save hpcx82/3027686 to your computer and use it in GitHub Desktop.
Spin lock implementation in Windows and depends on it a double-checked singleton.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// we use double-lock check in singleton to solve the problem we met in spinlock1.cpp, but hey, that itself is a lock, it has to use some atomic intrusion/memory barrier to solve this synchronization problem | |
template<class T> | |
class SingletonHolder | |
{ | |
private: | |
static volatile T* instance; | |
static volatile int m_lockObj; | |
SingletonHolder() {} | |
public: | |
static T* get() | |
{ | |
if(instance == NULL) | |
{ | |
// TODO: use RAII to make it exception safe. | |
Lock lock; | |
lock.lock(m_lockObj); | |
if(instance == NULL) | |
instance = new T(); | |
lock.unlock(m_lockObj); | |
} | |
return instance; | |
} | |
} | |
template<class T> SingletonHolder::instance = NULL; | |
template<class T> SingletonHolder::m_lockObj = 0; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The right way | |
class Lock | |
{ | |
void lock(volatile int* lockObj) | |
{ | |
while(true) | |
{ | |
// CAS: compare and swap | |
// synchronized: if(*lockObj == 0) *lockObj = 1; | |
if(interlockedCompareExchange(lockObj, 1, 0) == 0) | |
{ | |
// lock acquired | |
break; | |
} | |
} | |
} | |
// release the lock | |
void unlock(volatile int* lockObj) | |
{ | |
// lock released | |
*lockObj = 0; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The wrong way - the check and assignment is not atomic, there is a race condition there. | |
class Lock | |
{ | |
void lock(volatile int* lockObj) | |
{ | |
while(true) | |
{ | |
if(*lockObj == 0) | |
{ | |
*lockObj = 1; | |
break; | |
} | |
} | |
} | |
// release the lock | |
void unlock(volatile int* lockObj) | |
{ | |
// lock released | |
*lockObj= 0; | |
} | |
}; |
volatile在C++标准中的定义保证一个线程的修改,在另外一个线程中是可见的。
但在windows下,微软做了更多:保证volatile的读写不会被乱序优化 (编译时): http://msdn.microsoft.com/en-us/library/12a04hfd(v=vs.80).aspx
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
production-level的spinlock windows实现见此:http://www.codeproject.com/Articles/184046/Spin-Lock-in-C