I've been thinking about the double checked locking pattern in the last few days, and I couldn't understand why not replace the singleton pointer object check with a static variable.
Classic DCLP:
Code:
Singleton* Singleton::instance() {
if (pInstance == 0) {
Lock lock;
if (pInstance == 0)
{
pInstance = new Singleton;
}
}
I wanted to provide some solutions for on-demand, efficient singleton construction and access for Windows and Posix in a multi-threaded environment. If you don't have a strict requirement for on-demand construction (meaning the singleton is only created if need be) then the best solution is to simply create the singleton prior to thread creation. Another "rule-of-thumb" is to never access a singleton within a global object constructor or destructor.
As a reusable pattern, I prefer the concept of a "singleton constructor". The first example uses user-supplied memory barriers (membars) to ensure proper ordering of memory accesses. Posix doesn't have explicit membars, so this it more of a Windows approach - but could be ported to other systems:
Code:
/*------------------------------------------------------------------------------
SingletonConstruct -
Template class for constructing a singleton in an efficient and thread safe
manner. This object must be a static member of the class that you want to be
a singleton - this ensures m_p will be zero'd out during global construction
(which is single threaded)
NOTE: Do not use your singleton in a global object constructor or destructor.
------------------------------------------------------------------------------*/
template <typename T>
class SingletonConstruct : public no_copy
{
T *m_p;
CriticalSection m_cs;
public:
SingletonConstruct() : m_p(0) {}
~SingletonConstruct() {Unload();}
// NOTE: caller must guarantee that no references are being held
void Unload()
{
delete m_p;
}//Unload
T& Instance()
{
// atomic read with acquire membar semantics
T *p = InterlockedReadAcquire(&m_p);
if (!p)
{
CriticalSection::scoped_lock lock(m_cs);
p = m_p;
if (!p)
{
p = new T;
// atomic write with release membar semantics
InterlockedWriteRelease(&m_p, p);
}//if
}//if
return *p;
}//Instance
};//SingletonConstruct
// Example usage SingletonConstruct
class foo : public no_copy
{
static SingletonConstruct<foo> m_foo_sc;
friend class SingletonConstruct<foo>;
foo() {}
~foo() {}
public:
static foo& Instance() {return m_foo_sc.Instance();}
void display() {std::cout << "I'm the foo instance!" << std::endl;}
};//foo
// m_foo_sc is global which ensures it's construction prior to threading
SingletonConstruct<foo> foo::m_foo_sc;
The next example uses thread local storage (TLS) to avoid synchronization when taking the "fast path" of returning the already created singleton. Since TLS memory is unique per-thread, a Posix compliant implementation is possible.
Code:
/*------------------------------------------------------------------------------
tlsSingletonConstruct -
Demonstrates singleton construction in an efficient and thread safe manner
using TLS. It is assumed that TLS memory access is more efficient than
acquiring a lock. A Posix compliant implementation is possible using this
model.
------------------------------------------------------------------------------*/
template <typename T>
class tlsSingletonConstruct : public no_copy
{
T *m_p;
CriticalSection m_cs;
public:
tlsSingletonConstruct() : m_p(0) {}
~tlsSingletonConstruct() {Unload();}
// NOTE - caller must guarantee that no references are being held
void Unload()
{
delete m_p;
}//Unload
T& Instance()
{
// "__thread" represents TLS which is guaranteed to be initialized
// "early". An actual implementation may use compiler extensions to
// declare the static TLS here, or acquire TLS storage via API's within
// tlsSingletonConstruct's constructor.
static __thread bool g_created = false;
if (g_created)
return *m_p;
CriticalSection::scoped_lock lock(m_cs);
if (!m_p)
m_p = new T;
g_created = true;
return *m_p;
}//Instance
};//tlsSingletonConstruct
Last but not least for Posix is to simply use pthread_once(). The downside to this approach is that it's difficult to create a reusable pattern. The reason is because pthread_once() takes a function pointer with external C linkage, taking no arguments. So you can't (portably) use a static class member, and there's no argument to pass a 'this' pointer. But it's easy enough to implement by hand:
Code:
extern "C" void bar_create();
class bar
{
static bar *g_singleton;
static pthread_once_t g_once;
static void create() {g_singleton = new bar;}
friend void bar_create();
bar() {}
~bar() {}
public:
static bar& Instance()
{
pthread_once(&g_once, &bar_create);
return *g_singleton;
}//Instance
void display() {std::cout << "I'm the bar instance!" << std::endl;}
};//bar
bar* bar::g_singleton = 0;
pthread_once_t bar::g_once = PTHREAD_ONCE_INIT;
void bar_create() {bar::create();}
I've attached a complete implementation of the above code for Windows. Let me know of any questions/concerns.
Convert that post into an Article, and post it for publication
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010 In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
I wanted to provide some solutions for on-demand, efficient singleton construction and access for Windows and Posix in a multi-threaded environment. If you don't have a strict requirement for on-demand construction (meaning the singleton is only created if need be) then the best solution is to simply create the singleton prior to thread creation. Another "rule-of-thumb" is to never access a singleton within a global object constructor or destructor.
As a reusable pattern, I prefer the concept of a "singleton constructor". The first example uses user-supplied memory barriers (membars) to ensure proper ordering of memory accesses. Posix doesn't have explicit membars, so this it more of a Windows approach - but could be ported to other systems:
Code:
/*------------------------------------------------------------------------------
SingletonConstruct -
Template class for constructing a singleton in an efficient and thread safe
manner. This object must be a static member of the class that you want to be
a singleton - this ensures m_p will be zero'd out during global construction
(which is single threaded)
NOTE: Do not use your singleton in a global object constructor or destructor.
------------------------------------------------------------------------------*/
template <typename T>
class SingletonConstruct : public no_copy
{
T *m_p;
CriticalSection m_cs;
public:
SingletonConstruct() : m_p(0) {}
~SingletonConstruct() {Unload();}
// NOTE: caller must guarantee that no references are being held
void Unload()
{
delete m_p;
}//Unload
T& Instance()
{
// atomic read with acquire membar semantics
T *p = InterlockedReadAcquire(&m_p);
if (!p)
{
CriticalSection::scoped_lock lock(m_cs);
p = m_p;
if (!p)
{
p = new T;
// atomic write with release membar semantics
InterlockedWriteRelease(&m_p, p);
}//if
}//if
return *p;
}//Instance
};//SingletonConstruct
// Example usage SingletonConstruct
class foo : public no_copy
{
static SingletonConstruct<foo> m_foo_sc;
friend class SingletonConstruct<foo>;
foo() {}
~foo() {}
public:
static foo& Instance() {return m_foo_sc.Instance();}
void display() {std::cout << "I'm the foo instance!" << std::endl;}
};//foo
// m_foo_sc is global which ensures it's construction prior to threading
SingletonConstruct<foo> foo::m_foo_sc;
The next example uses thread local storage (TLS) to avoid synchronization when taking the "fast path" of returning the already created singleton. Since TLS memory is unique per-thread, a Posix compliant implementation is possible.
Code:
/*------------------------------------------------------------------------------
tlsSingletonConstruct -
Demonstrates singleton construction in an efficient and thread safe manner
using TLS. It is assumed that TLS memory access is more efficient than
acquiring a lock. A Posix compliant implementation is possible using this
model.
------------------------------------------------------------------------------*/
template <typename T>
class tlsSingletonConstruct : public no_copy
{
T *m_p;
CriticalSection m_cs;
public:
tlsSingletonConstruct() : m_p(0) {}
~tlsSingletonConstruct() {Unload();}
// NOTE - caller must guarantee that no references are being held
void Unload()
{
delete m_p;
}//Unload
T& Instance()
{
// "__thread" represents TLS which is guaranteed to be initialized
// "early". An actual implementation may use compiler extensions to
// declare the static TLS here, or acquire TLS storage via API's within
// tlsSingletonConstruct's constructor.
static __thread bool g_created = false;
if (g_created)
return *m_p;
CriticalSection::scoped_lock lock(m_cs);
if (!m_p)
m_p = new T;
g_created = true;
return *m_p;
}//Instance
};//tlsSingletonConstruct
Last but not least for Posix is to simply use pthread_once(). The downside to this approach is that it's difficult to create a reusable pattern. The reason is because pthread_once() takes a function pointer with external C linkage, taking no arguments. So you can't (portably) use a static class member, and there's no argument to pass a 'this' pointer. But it's easy enough to implement by hand:
Code:
extern "C" void bar_create();
class bar
{
static bar *g_singleton;
static pthread_once_t g_once;
static void create() {g_singleton = new bar;}
friend void bar_create();
bar() {}
~bar() {}
public:
static bar& Instance()
{
pthread_once(&g_once, &bar_create);
return *g_singleton;
}//Instance
void display() {std::cout << "I'm the bar instance!" << std::endl;}
};//bar
bar* bar::g_singleton = 0;
pthread_once_t bar::g_once = PTHREAD_ONCE_INIT;
void bar_create() {bar::create();}
I've attached a complete implementation of the above code for Windows. Let me know of any questions/concerns.
gg
Hi gg,
Let's take it to another level...
I really like your article, it's very interesting. However, your Singleton pattern is NOT thread safe. I can break it very easily. I bring out some issues first before I go into the "not safe" part.
Let us first see what you have done in your article.
You are using the DCL pattern (Double-Checked locking Optimization) of D. Schmidt. You modified it with thanks to Scott Meyers and Andrei Alexandrescu a link to those articles can be very interesting.
According to Andrew Koeing "Ruminations on C++" and Herb Sutter C++ "Coding Standards" the destructor should be made virtual. So, you should make your no_copy destructor virtual.
You explain the creation of the Singleton and not the destruction. Either you accept the memory leak or the weak construction.
You have locked the Instance method where the DCLP technique is used. However, the unload method is not guarded. You can now unload/delete the one and only instance while creating the SingletonObject. This means the code your wrote is incorrect and NOT thread safe!
T *p = InterlockedReadAcquire(&m_p);
if (!p)
{
CriticalSection::scoped_lock lock(m_cs);
p = m_p;
Please set the pointer back to NULL/0 when you delete it, so the statement above can be executed correctly without using a pointer which point to a deleted Singleton object. This means, if I put the creating and the destructing in different threads, your construction will fail and is not thread safe. So, what can we conclude? We can conclude that your example is still not thread safe.
The Display methods can be declared as const method.
Lets talk about the friend class you're using. It's like slapping the Object Oriented concept with both hands. I can still Unload the one and only instance. So, you shouldn't declare the entire class as friend but only the methods using.
P.S. for the next time you post a message and criticize people on details make sure your own creation is good enough.
To existing subscribers of this thread, our new contributor most likely found their way here from: http://www.codeproject.com/KB/thread...edLocking.aspx
I am "Member 4490530" and "Codeplug-gg" in the article discussion area.
>> However, the unload method is not guarded.
Guarding it is pointless if references to the singleton are still being used elsewhere. The semantics of the Unload() method are clearly commented - you must guarantee that no references are being held. That includes attempts to get a reference. Thread-safety between Unload() and Instance() was never claimed. Stating that they aren't thread-safe is just stating the obvious...
>> Please set the pointer back to NULL/0 when you delete it
Good catch. Two calls to Unload() would be bad. However, the ability to call Instance() after Unload() was never intended. Adding some assert()'s to catch this type of misuse wouldn't hurt.
Multiple threads calling Unload() and Instance() doesn't make a lot of sense to me, but despite that, I've added support for it in the latest version of my DCL object, "Once", and "SingletonConstruct":
Code:
#include <stdexcept>
#include <windows.h>
/*------------------------------------------------------------------------------
no_copy - Disallow copy semantics
------------------------------------------------------------------------------*/
class no_copy
{
protected:
no_copy() {}
~no_copy() {}
private:
no_copy(const no_copy&);
const no_copy& operator=(const no_copy&);
};//no_copy
/*------------------------------------------------------------------------------
scoped_lock -
Generalized template for Acquire()/Release() operations in the constructor
and destructor respectively
------------------------------------------------------------------------------*/
template<class sync_t>
class scoped_lock : public no_copy
{
sync_t &m_sync;
public:
explicit scoped_lock(sync_t &s) : m_sync(s) {m_sync.Acquire();}
~scoped_lock() {m_sync.Release();}
};//scoped_lock
/*------------------------------------------------------------------------------
CriticalSection - C++ version of a Win32 CS
------------------------------------------------------------------------------*/
class CriticalSection : public no_copy
{
CRITICAL_SECTION m_cs;
public:
typedef scoped_lock<CriticalSection> scoped_lock;
CriticalSection(bool bUseSpinCount = true, DWORD SpinCount = 4000)
{
if (bUseSpinCount &&
!InitializeCriticalSectionAndSpinCount(&m_cs, SpinCount))
throw std::runtime_error("InitCSAndSpinCount failure");
else
InitializeCriticalSection(&m_cs);
}//constructor
~CriticalSection() {::DeleteCriticalSection(&m_cs);}
void Acquire() {::EnterCriticalSection(&m_cs);}
void Release() {::LeaveCriticalSection(&m_cs);}
};//CriticalSection
//------------------------------------------------------------------------------
// Interlocked*Acquire/Release() functions only for Itanium Processor Family,
// (IPF), which we map to non-IPF Interlocked functions for other platforms
#if !defined(_M_IA64) && !defined(__IA64__)
# define InterlockedExchangeAddAcquire InterlockedExchangeAdd
# define InterlockedExchangeAddRelease InterlockedExchangeAdd
#endif
/*------------------------------------------------------------------------------
Once -
C++ implementation of "one-time initialization" among multiple threads. You
must ensure that construction of a Once object is thread-safe. For example,
Once definitions at global scope will ensures m_once will be zero'd out
during global object construction (which is single threaded). You can then
call one of the DoOnce() methods, or construct a Sentry object on the stack
to determine if one-time initialization should occur.
This is basically an implementation of double-check locking (DCL), which
can be tricky to get right - see the following:
"C++ and the Perils of Double-Checked Locking"
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
The proper solution is to ensure proper ordering/visibility of changes to
m_once. This is achieved via acquire/release memory barriers, via
InterlockedExchangeAddAcquire and InterlockedExchangeAddRelease.
------------------------------------------------------------------------------*/
class Once : public no_copy
{
LONG m_once;
CriticalSection m_cs;
friend class Sentry;
public:
class Sentry : public no_copy
{
Once &m_o;
bool m_bOwner;
bool m_bAcquiredCS;
public:
explicit Sentry(Once &o) : m_o(o), m_bOwner(false), m_bAcquiredCS(false)
{
if (InterlockedExchangeAddAcquire(&m_o.m_once, 0))
return; // m_once is non-zero, "once" has occurred already
// "once" hasn't happened yet
m_o.m_cs.Acquire();
m_bAcquiredCS = true;
m_bOwner = (m_o.m_once == 0);
}//constructor
~Sentry()
{
if (m_bOwner)
InterlockedExchangeAddRelease(&m_o.m_once, 1);
if (m_bAcquiredCS)
m_o.m_cs.Release();
}//destructor
bool OnceOwner() const {return m_bOwner;}
};//Sentry
Once() : m_once(0) {}
template <typename Obj_t>
bool DoOnce(Obj_t *obj, void (Obj_t::*mfn)())
{
Sentry s(*this);
if (s.OnceOwner())
(obj->*mfn)();
return s.OnceOwner();
}//DoOnce
template<class Functor_t>
bool DoOnce(const Functor_t &f)
{
Sentry s(*this);
if (s.OnceOwner())
f();
return s.OnceOwner();
}//DoOnce
#ifdef POINTLESS
// Once isn't enough for some folks...
// NOTE - Once object should be acquired before calling this method
void Reset() {InterlockedExchange(&m_once, 0);}
// Use our member CriticalSection for Acquire/Release semantics
void Acquire() {m_cs.Acquire();}
void Release() {m_cs.Release();}
typedef scoped_lock<Once> scoped_lock;
#endif
};//Once
/*------------------------------------------------------------------------------
SingletonConstruct -
Template class for constructing a singleton in an efficient and thread safe
manner. This object must be a static member of the class that you want to be
a singleton. This ensures m_once will be constructed during global object
construction (which is single threaded).
------------------------------------------------------------------------------*/
template <class T>
class SingletonConstruct : public no_copy
{
Once m_once;
T *m_p;
public:
SingletonConstruct() : m_p(0) {}
~SingletonConstruct() {Unload();}
// NOTE: 1) Caller must guarantee that no references are being held
// 2) This is thread-safe with respect to calls to Instance() when
// POINTLESS is defined.
// 3) Guaranteeing 1) makes 2) pointless...
void Unload()
{
#ifdef POINTLESS
Once::scoped_lock l(m_once);
// reset the Once object, this will block any calls to Instance()
// while we have the Once object acquired - ensuring that construction
// and destruction are mutually exclusive and thread-safe
m_once.Reset();
#endif
if (m_p) // yes, I know delete 0 doesn't hurt...
{
delete m_p;
m_p = 0;
}//if
}//Unload
T& Instance()
{
Once::Sentry s(m_once);
if (s.OnceOwner())
m_p = new T;
return *m_p;
}//Instance
};//SingletonConstruct
>> P.S. ...
Don't let emotions have any influence on the contents of your posts. I apologize if feelings were hurt. My only intention is to educate readers on what I know - and learn whatever I can in the process.
To existing subscribers of this thread, our new contributor most likely found their way here from: http://www.codeproject.com/KB/thread...edLocking.aspx
I am "Member 4490530" and "Codeplug-gg" in the article discussion area.
>> However, the unload method is not guarded.
Guarding it is pointless if references to the singleton are still being used elsewhere. The semantics of the Unload() method are clearly commented - you must guarantee that no references are being held. That includes attempts to get a reference. Thread-safety between Unload() and Instance() was never claimed. Stating that they aren't thread-safe is just stating the obvious...
>> Please set the pointer back to NULL/0 when you delete it
Good catch. Two calls to Unload() would be bad. However, the ability to call Instance() after Unload() was never intended. Adding some assert()'s to catch this type of misuse wouldn't hurt.
Multiple threads calling Unload() and Instance() doesn't make a lot of sense to me, but despite that, I've added support for it in the latest version of my DCL object, "Once", and "SingletonConstruct":
Code:
#include <stdexcept>
#include <windows.h>
/*------------------------------------------------------------------------------
no_copy - Disallow copy semantics
------------------------------------------------------------------------------*/
class no_copy
{
protected:
no_copy() {}
~no_copy() {}
private:
no_copy(const no_copy&);
const no_copy& operator=(const no_copy&);
};//no_copy
/*------------------------------------------------------------------------------
scoped_lock -
Generalized template for Acquire()/Release() operations in the constructor
and destructor respectively
------------------------------------------------------------------------------*/
template<class sync_t>
class scoped_lock : public no_copy
{
sync_t &m_sync;
public:
explicit scoped_lock(sync_t &s) : m_sync(s) {m_sync.Acquire();}
~scoped_lock() {m_sync.Release();}
};//scoped_lock
/*------------------------------------------------------------------------------
CriticalSection - C++ version of a Win32 CS
------------------------------------------------------------------------------*/
class CriticalSection : public no_copy
{
CRITICAL_SECTION m_cs;
public:
typedef scoped_lock<CriticalSection> scoped_lock;
CriticalSection(bool bUseSpinCount = true, DWORD SpinCount = 4000)
{
if (bUseSpinCount &&
!InitializeCriticalSectionAndSpinCount(&m_cs, SpinCount))
throw std::runtime_error("InitCSAndSpinCount failure");
else
InitializeCriticalSection(&m_cs);
}//constructor
~CriticalSection() {::DeleteCriticalSection(&m_cs);}
void Acquire() {::EnterCriticalSection(&m_cs);}
void Release() {::LeaveCriticalSection(&m_cs);}
};//CriticalSection
//------------------------------------------------------------------------------
// Interlocked*Acquire/Release() functions only for Itanium Processor Family,
// (IPF), which we map to non-IPF Interlocked functions for other platforms
#if !defined(_M_IA64) && !defined(__IA64__)
# define InterlockedExchangeAddAcquire InterlockedExchangeAdd
# define InterlockedExchangeAddRelease InterlockedExchangeAdd
#endif
/*------------------------------------------------------------------------------
Once -
C++ implementation of "one-time initialization" among multiple threads. You
must ensure that construction of a Once object is thread-safe. For example,
Once definitions at global scope will ensures m_once will be zero'd out
during global object construction (which is single threaded). You can then
call one of the DoOnce() methods, or construct a Sentry object on the stack
to determine if one-time initialization should occur.
This is basically an implementation of double-check locking (DCL), which
can be tricky to get right - see the following:
"C++ and the Perils of Double-Checked Locking"
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
The proper solution is to ensure proper ordering/visibility of changes to
m_once. This is achieved via acquire/release memory barriers, via
InterlockedExchangeAddAcquire and InterlockedExchangeAddRelease.
------------------------------------------------------------------------------*/
class Once : public no_copy
{
LONG m_once;
CriticalSection m_cs;
friend class Sentry;
public:
class Sentry : public no_copy
{
Once &m_o;
bool m_bOwner;
bool m_bAcquiredCS;
public:
explicit Sentry(Once &o) : m_o(o), m_bOwner(false), m_bAcquiredCS(false)
{
if (InterlockedExchangeAddAcquire(&m_o.m_once, 0))
return; // m_once is non-zero, "once" has occurred already
// "once" hasn't happened yet
m_o.m_cs.Acquire();
m_bAcquiredCS = true;
m_bOwner = (m_o.m_once == 0);
}//constructor
~Sentry()
{
if (m_bOwner)
InterlockedExchangeAddRelease(&m_o.m_once, 1);
if (m_bAcquiredCS)
m_o.m_cs.Release();
}//destructor
bool OnceOwner() const {return m_bOwner;}
};//Sentry
Once() : m_once(0) {}
template <typename Obj_t>
bool DoOnce(Obj_t *obj, void (Obj_t::*mfn)())
{
Sentry s(*this);
if (s.OnceOwner())
(obj->*mfn)();
return s.OnceOwner();
}//DoOnce
template<class Functor_t>
bool DoOnce(const Functor_t &f)
{
Sentry s(*this);
if (s.OnceOwner())
f();
return s.OnceOwner();
}//DoOnce
#ifdef POINTLESS
// Once isn't enough for some folks...
// NOTE - Once object should be acquired before calling this method
void Reset() {InterlockedExchange(&m_once, 0);}
// Use our member CriticalSection for Acquire/Release semantics
void Acquire() {m_cs.Acquire();}
void Release() {m_cs.Release();}
typedef scoped_lock<Once> scoped_lock;
#endif
};//Once
/*------------------------------------------------------------------------------
SingletonConstruct -
Template class for constructing a singleton in an efficient and thread safe
manner. This object must be a static member of the class that you want to be
a singleton. This ensures m_once will be constructed during global object
construction (which is single threaded).
------------------------------------------------------------------------------*/
template <class T>
class SingletonConstruct : public no_copy
{
Once m_once;
T *m_p;
public:
SingletonConstruct() : m_p(0) {}
~SingletonConstruct() {Unload();}
// NOTE: 1) Caller must guarantee that no references are being held
// 2) This is thread-safe with respect to calls to Instance() when
// POINTLESS is defined.
// 3) Guaranteeing 1) makes 2) pointless...
void Unload()
{
#ifdef POINTLESS
Once::scoped_lock l(m_once);
// reset the Once object, this will block any calls to Instance()
// while we have the Once object acquired - ensuring that construction
// and destruction are mutually exclusive and thread-safe
m_once.Reset();
#endif
if (m_p) // yes, I know delete 0 doesn't hurt...
{
delete m_p;
m_p = 0;
}//if
}//Unload
T& Instance()
{
Once::Sentry s(m_once);
if (s.OnceOwner())
m_p = new T;
return *m_p;
}//Instance
};//SingletonConstruct
>> P.S. ...
Don't let emotions have any influence on the contents of your posts. I apologize if feelings were hurt. My only intention is to educate readers on what I know - and learn whatever I can in the process.
gg
Hi gg,
I'll fix, update and add extra references to any websites where people have posted their messages. We all do it for the readers (the majority at least).
Some people gave me input for the article and I was happy to get it. Not only it will mature my article but it will catch a wide range of people looking for this specific problem. As I mentioned before, I really like your post and I think you did a great job.
I'll explain the DCLP of Schmidt with the volatile and I'll bring out the ideas Mr. Meyer. I will add a big note that this pattern of Schmidt is not thread save eventhough volatile(s) is added. Finally I will refer to this link with your name and a big thanks for the input.
My apologies for my last reaction. I'm tired of the DCLP discussions
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.