首页 > 代码库 > C++之多线程分析
C++之多线程分析
在我们开始讲线程这前先了解一下线程的载体—进程。进程,它是一个正在运行的程序的实例,是一个程序在其自身的地址空间的一次执行活动。进程是资源申请、调度、和独立运行的基本单位。进程有两部分组成:
1、操作系统用来管理进程的内核对象,内核对象是系统用来存放关于进程的统计信息的地方,它是操作系统内部分配的一块内存块,该内存块是一种数据结构,其成员负责维护该对象的各种信息。
2、地址空间,它包含所有可执行模块、dll模块的代码和数据,也包含动态内存分配的空间。
线程---操作系统调度的最小单位。线程包含在进程中,是进程中实际运行的单位。一个进程中可以同时运行多个线程,每个线程可以执行不同的任务,这就是所谓的多线程。同一进程中的多个线程将共享该进程中的全部系统资源,如虚拟地址空间、文件描述符和信号处理等,但是同一个进程中的多个线程都有各自的调用栈、寄存器环境和线程本地存储。
对于单核(单CPU)系统来说,即便处理器一次只能运行一个线程,但是操作系统通过时间片轮转技术,在不同的线程之间进行切换,让用户产生可以同时处理多个任务的错觉,这样的程序运行机制称为软件的多线程。
对于多核(多个CPU)系统来说,这样的系统能同时进行真正的多线程多任务处理。这种运行机制可以称为硬件的多线程技术。
多线程程序作为一种多任务、并发的工作方式,当然有以下的优点:
1)、提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。
2)、使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
3)、改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
如下是我写一个跨平台的线程例子:
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
C++之多线程分析