We are going to have some .h files in this example.
Lock.h
//Example from http://www.relisoft.com/Win32/active.html
#if !defined _LOCK_H_
#define _LOCK_H_
#include "Mutex.h"
class Lock
{
public:
// Acquire the state of the semaphore
Lock ( Mutex & mutex )
: _mutex(mutex)
{
_mutex.Acquire();
}
// Release the state of the semaphore
~Lock ()
{
_mutex.Release();
}
private:
Mutex & _mutex;
};
#endif
Mutex.h
//Example from http://www.relisoft.com/Win32/active.html
#if !defined _MUTEX_H_
#define _MUTEX_H_
class Mutex
{
friend class Lock;
public:
Mutex () { InitializeCriticalSection (& _critSection); }
~Mutex () { DeleteCriticalSection (& _critSection); }
private:
void Acquire ()
{
EnterCriticalSection (& _critSection);
}
void Release ()
{
LeaveCriticalSection (& _critSection);
}
CRITICAL_SECTION _critSection;
};
#endif
Singleton.h
#include "Lock.h"
#include "Mutex.h"
class aSingletonClass
{
public:
//method to get Instance of class
static aSingletonClass *getInstance( void )
{
//Note that the class is only created when this method is called first time
if(!instance_)
instance_ = new aSingletonClass;
return instance_;
}
//method to delete Instance of class
static void deleteInstance( void )
{
if(instance_)
delete instance_;
instance_ = NULL; //important as this can create dead reference problems
}
void printSomething(char *name, int count)
{
Lock guard(mutex_);
std::cout << name << " loop " << count << std::endl;
}
private:
//variable to store the instance of singleton
static aSingletonClass *instance_;
//default constructor should be private to prevent instantiation
aSingletonClass() {};
//destructor should be made private so no one can delete this accidently
~aSingletonClass() {};
//We also need to prevent copy being created of the object
aSingletonClass(const aSingletonClass&);
Mutex mutex_;
};
Thread.cpp
//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//This shows example of Multithreading, thread sync, Mutex
#include <windows.h>
#include <process.h>
#include <iostream>
#include "Singleton.h"
using namespace std;
aSingletonClass* aSingletonClass::instance_ = NULL;
void Func1(void *);
void Func2(void *);
int main()
{
HANDLE hThreads[2];
aSingletonClass *someVar = NULL;
//Create Instance
someVar = aSingletonClass::getInstance();
//Create two threads and start them
hThreads[0] = (HANDLE)_beginthread(Func1, 0, NULL);
hThreads[1] = (HANDLE)_beginthread(Func2, 0, NULL);
//Makes sure that both the threads have finished before going further
WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
cout << "Main exit" << endl;
return 0;
}
void Func1(void *P)
{
int Count;
for (Count = 1; Count < 11; Count++)
{
aSingletonClass::getInstance()->printSomething("Func1", Count);
}
return;
}
void Func2(void *P)
{
int Count;
for (Count = 10; Count > 0; Count--)
{
aSingletonClass::getInstance()->printSomething("Func2", Count);
}
return;
}
The Output is as follows:
it doesn't synchronized in my computer (windows 7 with Intel core 2)
ReplyDeletePlease copy and paste your output in comments and then we can see what you are getting.
ReplyDeleteI got the same problem, my output is this:
ReplyDelete[code]
Func1 loop 1
Func1 loop 2
Func1 loop 3
Func1 loop 4
Func1 loop 5
Func1 loop 6
Func1 loop 7
Func1 loop 8
Func1 loop 9
Func1 loop 10
Func2 loop 10
Func2 loop 9
Func2 loop 8
Func2 loop 7
Func2 loop 6
Func2 loop 5
Func2 loop 4
Func2 loop 3
Func2 loop 2
Func2 loop 1
Main exit
[/code]
Compiled with VS2008, Vista 64 bit, Intel Quad Q9660
the same, doesnot work.
ReplyDeleteu need 1) change to
ReplyDeletevoid Acquire ()
{
while(mutexAcquired){Sleep(1);};
EnterCriticalSection (& _critSection);
mutexAcquired = true;
}
void Release ()
{
LeaveCriticalSection (& _critSection);
mutexAcquired = false;
}
2) put Sleep(1) f.e. after
aSingletonClass::getInstance()->printSomething(...
Without delay first thread completing processing before second one starts)
Strange I didnt see this problem of multiple PC's.
ReplyDeleteWhat value would you assign mutexAcquired initially? and where would you declare it?
ReplyDeleteThanks!
I guess this comment is based on the earlier comment. mutexAcquired should be set to false in Mutex constructor.
ReplyDeleteAny Answers/suggestions for this Question?
ReplyDeleteIf one uses a friend function in the singleton class declaration, then its possible to create multiple instances???
Bharath, yes you can create multiple instances but what is the point of using Singleton?
ReplyDeletedo we also have asynchronous multithreading in C++ ? how to code synchronous and asynsynchronous multi threading in c++?
ReplyDeleteRaksha, if you remove Lock guard(mutex_); it will become asynchronous. By default the threads are asynchronous but you can use approaches like Mutex to make it synchronous.
ReplyDeleteHi Zahid,
ReplyDeleteShould there be a mutex protecting
LOCK()
if(!instance_)
instance_ = new aSingletonClass; so that
UNLOCK()
So that it is executed atomically? I feel if this is not done multiple threads may perform this 'new' command simultaneously creating multiple instances which may create a memory leak.
Your Thoughts
Cheers,
Hi Michael, yes you can do that. Singleton's should be created in the main function and should be created before any threads are created. I am sure not everyone strictly follows this so a Mutex would certainly help.
ReplyDeleteHey Zahid,
ReplyDeleteI see - you create the instance before everything starts multitasking so there is no contention. Great idea - thanks for the help and fast response :)
Cheers,
Michael
Zahid, thanks for this interesting blog. But I tested it in my computer(win7+core8+vs2008) and got the different result from yours, which was also pointed out by two anonymous readers. Could you tell me what configuration I did wrong ? thanks.
ReplyDeleteFunc1 loop 1
Func1 loop 2
Func1 loop 3
Func1 loop 4
Func1 loop 5
Func1 loop 6
Func1 loop 7
Func1 loop 8
Func1 loop 9
Func1 loop 10
Func2 loop 10
Func2 loop 9
Func2 loop 8
Func2 loop 7
Func2 loop 6
Func2 loop 5
Func2 loop 4
Func2 loop 3
Func2 loop 2
Func2 loop 1
Main exit
See comment of Oct 22, 2010 09:06 AM.
ReplyDelete