C++のマルチスレッド解析
5997 ワード
スレッドについて説明する前に、スレッドのベクターであるプロセスについて説明します.プロセスは、実行中のプログラムのインスタンスであり、プログラム自身のアドレス空間での実行アクティビティです.プロセスは、リソース申請、スケジューリング、および独立して実行される基本単位です.プロセスには2つの部分があります.
1、オペレーティングシステムはプロセスを管理するためのカーネルオブジェクトであり、カーネルオブジェクトはシステムがプロセスに関する統計情報を格納するための場所であり、オペレーティングシステム内部に割り当てられたメモリブロックであり、このメモリブロックはデータ構造であり、そのメンバーはそのオブジェクトの各情報を維持する責任を負う.
2、すべての実行可能モジュール、dllモジュールのコードとデータを含み、動的メモリ割り当ての空間も含むアドレス空間.
スレッド---オペレーティングシステムのスケジューリングの最小単位.スレッドはプロセスに含まれ、プロセスで実際に実行される単位です.1つのプロセスで複数のスレッドを同時に実行でき、各スレッドは異なるタスクを実行できます.これはいわゆるマルチスレッドです.同じプロセス内の複数のスレッドは、仮想アドレス空間、ファイル記述子、信号処理など、プロセス内のすべてのシステムリソースを共有しますが、同じプロセス内の複数のスレッドには、それぞれの呼び出しスタック、レジスタ環境、スレッドがローカルに格納されます.
シングルコア(シングルCPU)システムでは,プロセッサが一度に1つのスレッドしか実行できないとしても,オペレーティングシステムはタイムスライスローテーション技術により異なるスレッド間を切り替え,複数のタスクを同時に処理できると錯覚するプログラム実行メカニズムをソフトウェアのマルチスレッドと呼ぶ.
マルチコア(複数のCPU)システムにとって、このようなシステムは、真のマルチスレッドマルチタスク処理を同時に行うことができる.この動作メカニズムは、ハードウェアのマルチスレッド技術と呼ぶことができる.
マルチスレッド・プログラムは、マルチタスク、同時動作の1つとして、もちろん以下の利点があります.
1)、アプリケーションの応答を高める.これはグラフィックインタフェースのプログラムに特に意味があり、1つの操作に時間がかかると、システム全体がこの操作を待っています.このとき、プログラムはキーボード、マウス、メニューの操作に応答しません.マルチスレッド技術を使用して、時間のかかる操作(time consuming)を新しいスレッドに配置することで、このような気まずい状況を避けることができます.
2)、マルチCPUシステムをより有効にする.オペレーティングシステムは、スレッド数がCPU数以下の場合、異なるスレッドが異なるCPU上で動作することを保証します.
3)、プログラム構造を改善する.1つの長くて複雑なプロセスは、複数のスレッドに分けて、いくつかの独立したまたは半独立した実行部分になることを考慮することができ、このようなプログラムは理解と修正に有利である.
次のように、プラットフォーム間でスレッドを作成します.
1、オペレーティングシステムはプロセスを管理するためのカーネルオブジェクトであり、カーネルオブジェクトはシステムがプロセスに関する統計情報を格納するための場所であり、オペレーティングシステム内部に割り当てられたメモリブロックであり、このメモリブロックはデータ構造であり、そのメンバーはそのオブジェクトの各情報を維持する責任を負う.
2、すべての実行可能モジュール、dllモジュールのコードとデータを含み、動的メモリ割り当ての空間も含むアドレス空間.
スレッド---オペレーティングシステムのスケジューリングの最小単位.スレッドはプロセスに含まれ、プロセスで実際に実行される単位です.1つのプロセスで複数のスレッドを同時に実行でき、各スレッドは異なるタスクを実行できます.これはいわゆるマルチスレッドです.同じプロセス内の複数のスレッドは、仮想アドレス空間、ファイル記述子、信号処理など、プロセス内のすべてのシステムリソースを共有しますが、同じプロセス内の複数のスレッドには、それぞれの呼び出しスタック、レジスタ環境、スレッドがローカルに格納されます.
シングルコア(シングルCPU)システムでは,プロセッサが一度に1つのスレッドしか実行できないとしても,オペレーティングシステムはタイムスライスローテーション技術により異なるスレッド間を切り替え,複数のタスクを同時に処理できると錯覚するプログラム実行メカニズムをソフトウェアのマルチスレッドと呼ぶ.
マルチコア(複数のCPU)システムにとって、このようなシステムは、真のマルチスレッドマルチタスク処理を同時に行うことができる.この動作メカニズムは、ハードウェアのマルチスレッド技術と呼ぶことができる.
マルチスレッド・プログラムは、マルチタスク、同時動作の1つとして、もちろん以下の利点があります.
1)、アプリケーションの応答を高める.これはグラフィックインタフェースのプログラムに特に意味があり、1つの操作に時間がかかると、システム全体がこの操作を待っています.このとき、プログラムはキーボード、マウス、メニューの操作に応答しません.マルチスレッド技術を使用して、時間のかかる操作(time consuming)を新しいスレッドに配置することで、このような気まずい状況を避けることができます.
2)、マルチCPUシステムをより有効にする.オペレーティングシステムは、スレッド数がCPU数以下の場合、異なるスレッドが異なるCPU上で動作することを保証します.
3)、プログラム構造を改善する.1つの長くて複雑なプロセスは、複数のスレッドに分けて、いくつかの独立したまたは半独立した実行部分になることを考慮することができ、このようなプログラムは理解と修正に有利である.
次のように、プラットフォーム間でスレッドを作成します.
Mutex.h
#ifndef HEART_MKITHEART_MMUTEX_H
#define HEART_MKITHEART_MMUTEX_H
#ifdef WIN32
# include <windows.h>
#else
# include <pthread.h>
#endif
#ifdef WIN32
typedef CRITICAL_SECTION MKIT_MUTEX_SECTION;
# define MKIT_MUTEX_INIT ::InitializeCriticalSection
# define MKIT_MUTEX_DESTROY ::DeleteCriticalSection
# define MKIT_MUTEX_LOCK ::EnterCriticalSection
# define MKIT_MUTEX_UNLOCK ::LeaveCriticalSection
#else
typedef pthread_mutex_t MKIT_MUTEX_SECTION;
# define MKIT_MUTEX_INIT pthread_mutex_init
# define MKIT_MUTEX_DESTROY pthread_mutex_destroy
# define MKIT_MUTEX_LOCK pthread_mutex_lock
# define MKIT_MUTEX_UNLOCK pthread_mutex_unlock
#endif
class Mutex
{
public:
Mutex()
{
MKIT_MUTEX_INIT(&m_mutex
#ifndef _WIN32
, NULL
#endif
);
}
virtual ~Mutex() {MKIT_MUTEX_DESTROY(&m_mutex);}
virtual void Lock() const {MKIT_MUTEX_LOCK(&m_mutex);}
virtual void Unlock() const { MKIT_MUTEX_UNLOCK(&m_mutex); }
private:
mutable MKIT_MUTEX_SECTION m_mutex;
};
class AutoLock
{
public:
AutoLock(const Mutex& mutex, bool autolocked = true) : m_mutex(&mutex), m_locked(true)
{
if(autolocked)
{
m_mutex->Lock();
m_locked = autolocked;
}
};
~AutoLock()
{
if(m_locked)
{
m_mutex->Unlock();
}
};
private:
const Mutex* m_mutex;
bool m_locked;
};
#ifndef LOCK
# define LOCK(mutex) AutoLock locker(mutex)
#endif
#endif//HEART_MKITHEART_MMUTEX_H
Thread.h
#ifndef HEART_MKITHEART_MTHREAD_H
#define HEART_MKITHEART_MTHREAD_H
#include "Mutex.h"
#define RET_SUCCEED 0
class Runnable
{
public:
virtual void Run() = 0;
};
class Thread : public virtual Runnable
{
Thread(const Thread&);
const Thread& operator=(const Thread&);
public:
Thread();
~Thread();
#ifdef WIN32
static unsigned int WINAPI ThreadFun(void* t);
#else
static void* ThreadFun(void* t);
#endif
int Start(void);
int Stop(void);
inline bool IsRunning(void) { return m_running; }
inline void SetRunning(bool x) { m_running = x; }
inline unsigned short GetWaitTime(void) { return m_waitTime; }
inline void SetWaitTime(unsigned short uTime) { m_waitTime = uTime;}
inline void SetRunnable(Runnable* pRunnable){ m_runnable = pRunnable; }
public :
virtual void Run();
protected:
void WatiTime(int mTime);
private:
#ifdef WIN32
HANDLE m_handle;
unsigned int m_threadID;
#else
pthread_t m_thread_t;
pthread_attr_t m_attr;
#endif
private:
unsigned short m_waitTime;
bool m_running;
Runnable* m_runnable;
Mutex m_mutex;
};
#endif//HEART_MKITHEART_MTHREAD_H
Thread.cpp
#ifdef WIN32
# include <process.h>
#else
# include <sys/time.h>
# include <sys/types.h>
#endif
#include "Thread.h"
Thread::Thread() : m_handle(0), m_runnable(0), m_running(false), m_waitTime(40)
{
}
Thread::~Thread()
{
Stop();
}
void Thread::Run()
{
if(m_runnable)
{
m_mutex.Lock();
m_runnable->Run();
m_mutex.Unlock();
}
WatiTime(m_waitTime);
}
#ifdef WIN32
unsigned int Thread::ThreadFun( void* t )
#else
void * Thread::ThreadFun( void* t )
#endif
{
Thread *p = (Thread*)(t);
if(t)
{
while (p->IsRunning())
{
p->Run();
}
#ifdef WIN32
_endthreadex(0);
#else
pthread_exit((void*)0);
#endif
}
return RET_SUCCEED;
}
int Thread::Start( void )
{
if(!IsRunning())
{
#ifdef WIN32
m_handle = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, this, 0, &m_threadID);//CREATE_SUSPENDED
#else
pthread_attr_init(&m_attr);
pthread_attr_setdetachstate(&m_attr, PTHREAD_CREATE_DETACHED);
if (-1 == pthread_create(&m_thread_t, &m_attr, ThreadFun, this))
{
SetRunning(false);
return -1;
}
#endif
SetRunning(true);
}
return RET_SUCCEED;
}
int Thread::Stop( void )
{
if (IsRunning())
{
m_mutex.Lock();
SetRunning(false);
m_mutex.Unlock();
}
#ifdef Win32
if(m_handle)
{
::WaitForSingleObject(m_handle, 50);
::CloseHandle(m_handle);
m_handle = NULL;
}
#endif
return RET_SUCCEED;
}
#ifdef WIN32
void Thread::WatiTime(int mTime)
{
Sleep(mTime);
}
#else
pthread_cond_t g_timer_cond;
pthread_mutex_t g_timer_mutex;
void Thread::WatiTime(int mTime)
{
struct timeval temp_timeout;
gettimeofday(&temp_timeout, 0);
struct timespec timeOut;
timeOut.tv_sec = temp_timeout.tv_sec;
timeOut.tv_nsec = (temp_timeout.tv_usec + mTime * 1000) * 1000;
pthread_cond_timedwait(&g_timer_cond, &g_timer_mutex, &timeOut);
}
#endif