多线程编程之线程的封装
来源:互联网 发布:如何评价兄弟连 知乎 编辑:程序博客网 时间:2024/05/21 19:28
一. 多线程要考虑的问题
前人总结出,一个线程安全的class应当满足的条件:
1. 从多个线程访问时,其表现出正确的行为,无论操作系统如何调度这些线程,无论这些线程的执行顺序如何交织。
2. 调用端代码无需额外的同步或其他协调动作
1. 线程访问资源安全(线程同步问题),这个问题,可用Mutex封装临界区,我的另一篇blog里有介绍.
2. 线程退出安全(主线程结束前线程安全退出),可在主线程结束时,在对象析构里等待线程退出再析构.
3. 跨线程使用的对象的生命周期的控制,要保证对象(指针)不再被使用时才析构。为了安全,少费精力,还是用shared_ptr代替原始指针吧。shared_ptr是boost库的智能指针,现在已加入标准库中,用法不说了,说一下线程中使用注意事项吧。
shared_ptr的线程安全:
shared_ptr的线程安全级别与内建类型一样,多个线程同时对一个shared_ptr进行读操作时是安全的,多个线程同时对多个shared_ptr进行写操作时是安全的,其余都是未定义的。
shared_ptr作为函数参数:
因为拷贝shared_ptr是要修改引用计数的,所以拷贝shared_ptr比拷贝原始指针成本要高,多数情况下可以以reference to const方式传递,只需要在最外层的函数有个实体对象,以后都可以用reference to const来使用这个shared_ptr。
二. 一个封装好的线程类
下面我写了个线程封装类(windows平台),线程时使用它能少写一些代码~ 源码呈上:
#ifndef HBASE_HTHREAD_H__#define HBASE_HTHREAD_H__#include <Windows.h>#ifdef Xxx_CALLBACK#include <Core/Core.h>#endif/** 在类A中使用HThread类: * 将HThread类的对象作为类A的成员. * Start函数,启动一个线程 * WaitExit函数,在A的析构里调用,保证在主线程退出前线程退出. * 注意:一个HThread类同时最多只能运行一个线程。 * 如果使用Callback封装unsigned (__stdcall * _start_address) (void *)函数,使用更灵活. */class HThread{public: HThread(); ~HThread();#ifdef Xxx_CALLBACK bool Start(Xxx::Callback _cb);#endif bool Start(unsigned (__stdcall * _start_address) (void *), void * _arg_list); int WaitExit(); bool IsRunning(); void Detach(); bool IsOpen() const { return (NULL != handle_); } HANDLE GetHandle() const { return handle_; }protected:#ifdef Xxx_CALLBACK static unsigned __stdcall ThreadRuntime(void* p);#endifprivate: HThread(const HThread&); HThread& operator=(const HThread&);private: HANDLE handle_;};#endif
#ifndef HBASE_HTHREAD_H__#define HBASE_HTHREAD_H__#include <Windows.h>#ifdef Xxx_CALLBACK#include <Core/Core.h>#endif/** 在类A中使用HThread类: * 将HThread类的对象作为类A的成员. * Start函数,启动一个线程 * WaitExit函数,在A的析构里调用,保证在主线程退出前线程退出. * 注意:一个HThread类同时最多只能运行一个线程。 * 如果使用Callback封装unsigned (__stdcall * _start_address) (void *)函数,使用更灵活. */class HThread{public: HThread(); ~HThread();#ifdef Xxx_CALLBACK bool Start(Xxx::Callback _cb);#endif bool Start(unsigned (__stdcall * _start_address) (void *), void * _arg_list); int WaitExit(); bool IsRunning(); void Detach(); bool IsOpen() const { return (NULL != handle_); } HANDLE GetHandle() const { return handle_; }protected:#ifdef Xxx_CALLBACK static unsigned __stdcall ThreadRuntime(void* p);#endifprivate: HThread(const HThread&); HThread& operator=(const HThread&);private: HANDLE handle_;};#endif
三. 根据任务类型封装的线程类
在用线程处理问题时常常分两种情况:
A. 这个线程只做一件事,或循环做一件事情,做完这件事情之后就不再用它了,此时就要结束这个线程,称这种线程为单任务型。
B. 启动一个线程后,有个事情A需要在线程里完成,此时把任务A交给线程,没过多久又有个任务B要做,再把B交给这个线程去完成,也就是说这个线程能完成各种类型的任务,这种类型的线程称为多任务型,如果管理多个线程,就成线程池了。
单任务型适合用于耗时的重复性操作,比如上传1000张图片,这种线程为该任务而生,任务结束线程也就结束了。
多任务型线程长期活着,接各种耗时短的杂活,有时候会下载个文件,有时候数据库插入个图片。
说了这么多,看代码吧~
#ifndef MATERIAL_THREAD_H__#define MATERIAL_THREAD_H__#include <Windows.h>#include <Core/Core.h>#include <deque>class TaskThreadBase{public: TaskThreadBase(); virtual ~TaskThreadBase(); virtual int WaitExit(); bool IsRunning(); void Detach(); bool IsOpen() const { return (NULL != handle_); } HANDLE GetHandle() const { return handle_; }private: TaskThreadBase(const TaskThreadBase&); TaskThreadBase& operator=(const TaskThreadBase&);protected: HANDLE handle_; bool running_;};class TaskThread : public TaskThreadBase{public: TaskThread(); ~TaskThread(); bool Start(Upp::Callback _cb); bool Start(unsigned (__stdcall * _start_address) (void *), void * _arg_list);protected: static unsigned __stdcall ThreadRuntime(void* p);};class MutiTaskThread : public TaskThreadBase{private: struct Task { Task() {} Task(Upp::Callback cb) : cb(cb) {} Upp::Callback cb; };public: MutiTaskThread(); ~MutiTaskThread(); void SetMaxTaskCount(size_t task_count); bool Start(); bool AddTask(Upp::Callback cb, bool priority = false); virtual int WaitExit(); private: static unsigned __stdcall ThreadRuntime(void* p); void Run(); void DoTask(const Task& task); void RequestStop();private: std::deque<Task> tasks_; size_t max_task_count_; Upp::Mutex mutex_; Upp::Semaphore semaphore_; bool quit_;};#endif
- 多线程编程之线程的封装
- 多线程编程之线程的封装
- 多线程编程之四 线程的同步
- 多线程编程之线程取消
- 多线程编程之线程通信
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步(转载)
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 多线程编程之四——线程的同步
- 【Java工具】将一个对象转换成Map
- MFC 非模态对话框 创建 销毁
- 论现在的html5有多火?
- Linux服务器Cache占用过多内存导致系统内存不足问题的排查解决
- HLOI2016滚粗记
- 多线程编程之线程的封装
- Tortoise SVN 加载路径中包含中文字符
- 一点小问题
- UI控件笔记(十六):UI之Uibutton,UIview,UIlbel等初始化的封装
- CodeIgniter3.0+Nginx的伪静态配置
- 关于<< 和>>操作
- java学习笔记5.17
- 40亿数据Map插入
- uva 1388