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

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-07-30 13:49:36

C++多线程分析的相关文章

Android多线程分析之四:MessageQueue的实现

罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前面两篇文章<Android多线程分析之二:Thread的实现>,<Android多线程分析之三:Handler,Looper的实现>中分别介绍了 Thread 的创建,运行,销毁的过程以及 Thread与 Handler,Looper 之间的关联:Thread 在其 run() 方法中创建和运行消息处理循环 Looper,而 Looper::loop() 方法不断地从 Messag

Android多线程分析之二:Thread的实现

Android多线程分析之二:Thread 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前文<Android多线程分析之一:使用Thread异步下载图像>中演示了如何使用 Thread 处理异步事务.示例中这个 Java Thread 类都是位于 Framework 层的类,它自身是通过 JNI 转调 dalvik 里面的 Thread 相关方法实现的.因此要分析 Androd 中的线程,就需要分析这两层中的与线程相关的代码,这就是本文要

Android多线程分析之一:使用Thread异步下载图像

罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 打算整理一下对 Android Framework 中多线程相关知识的理解,主要集中在 Framework 层的 Thread, Handler, Looper, MessageQueue, Message, AysncTask,当然不可避免地要涉及到 native 方法,因此也会分析 dalvik 中和线程以及消息处理相关的代码:如 dalvik 中的 C++ Thread 类以及 Message

Android多线程分析之五:使用AsyncTask异步下载图像

Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<Android多线程分析之中的一个:使用Thread异步下载图像>中.曾演示了怎样使用 Thread 来完毕异步任务. Android 为了简化在 UI 线程中完毕异步任务(毕竟 UI 线程是 app 最重要的线程).实现了一个名为 AysncTask 的模板类.使用 AysncTask 能够在异步任务进行的同

DICOM:DICOM开源库多线程分析之“ThreadPoolQueue in fo-dicom”

背景: 上篇博文介绍了dcm4chee中使用的Leader/Follower线程池模型,主要目的是节省上下文切换,提高运行效率.本博文同属[DICOM开源库多线程分析]系列,着重介绍fo-dicom中使用的ThreadPoolQueue线程池. ThreadPoolQueue in fo-dicom: 先看一下ThreadPoolQueue代码中自定义的数据结构, public class ThreadPoolQueue<T> { private class WorkItem { public

Android多线程分析之三:Handler,Looper的实现

Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前文<Android多线程分析之二:Thread的实现>中已经具体分析了Android Thread 是怎样创建,执行以及销毁的,其重点是对对应 native 方法进行分析,今天我将聚焦于 Android Framework 层多线程相关的类:Handler, Looper, MessageQueue, Message 以及它们与

单例模式中的多线程分析

谈到单例模式,我们立马会想到饿汉式和懒汉式加载,所谓饿汉式就是在创建类时就创建好了实例,懒汉式在获取实例时才去创建实例,即延迟加载. 饿汉式: Java代码 package com.bijian.study; public class Singleton { private static Singleton instance = null; private static String lock = new String(); public static Singleton getInstance

Android多线程分析之中的一个:使用Thread异步下载图像

罗朝辉 (http://blog.csdn.net/kesalin) CC 许可.转载请注明出处 打算整理一下对 Android Framework 中多线程相关知识的理解.主要集中在 Framework 层的 Thread, Handler, Looper, MessageQueue, Message, AysncTask,当然不可避免地要涉及到 native 方法,因此也会分析 dalvik 中和线程以及消息处理相关的代码:如 dalvik 中的 C++ Thread 类以及 Message

JAVA-初步认识-第十二章-JVM中的多线程分析

一. 我们学java程序学到现在,到底是多线程的,还是单线程的?(现实中多线程是一直存在的,我们只是才开始学习这个概念而已,没学过不代表不存在.) 虚拟机的启动本身就依赖了多条线程,为什么? 举例来看,(举实例来研究多线程) New了三个匿名对象,画一个堆内存演示一下. 左边是栈,右边是堆.栈里面有主函数,主函数里有代码.堆里面开始创建对象,匿名对象一创建完就是垃圾了(没有指向),现在有三个垃圾. 主函数里面代码有很多,它继续在执行. 从这里面立刻就可以得到第一点,就是我们的java虚拟机在运行

Java多线程分析案例

1. 多线程的创建方式 (1).继承 Thread类:但Thread本质上也是实现了Runnable 接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过 Thread 类的 start()实例方法.start()方法是一个 native 方法,它将启动一个新线程,并执行run()方法.这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法.例如:继承Thread类实现多线程,并在合适的地方启动