POSIX线程(POSIX threads):
简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。Windows操作系统也有其移植版pthreads-win32;
在Windows上:官方网站:http://sourceware.org/pthreads-win32/ 下载后简单配置就可以了;
更多信息可以网上查找;
这里要说的是:
1:pthread:是一个可以跨平台的线程,因为有了Windows的移植版本,通常可以在vsIDE中编写代码(还是VS IDE强大),然后在完成后,移植到其他系统;
2:pthread:和createthread的性质比较相近,其内部实现是Windows函数_beginthreadex(和AfxBeginThread不同,具体可以查看我以前的文章);pthread也比较简单;
所以建议可以用pthread;
这里对pthread简单封装一下,前面我讲过一篇文章《VC退出线程的方法》,这里简单封装一下pthread,实现线程的安全退出;
读者可以根据具体需求修改类的实现;
在pthread中没有cevent,所以要用到相近的方法:pthread_cond_wait;
简单举例(这个例子转自:http://blog.csdn.net/hudashi/article/details/7709421 ):
简单说明:在线程中pthread_cond_wait会阻塞线程,直到pthread_cond_broadcast(&mycond)(或者pthread_cond_signal(&m_mycond);)触发后,才继续往下执行;
pthread_mutex_t mymutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mymutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
void *mythread1(void *param)
{
printf("begin mythread1.\n");
pthread_mutex_lock(&mymutex1);
printf("wait in mythread1.\n");
pthread_cond_wait(&mycond,&mymutex1);
for ( int n = 0 ; n<100; n++ )
{
std::cout<< "mythread1: " << n << std::endl;
Sleep(100);
}
pthread_mutex_unlock(&mymutex1);
printf("end mythread1.\n");
return NULL;
}
void *mythread2(void *param)
{
printf("begin mythread2.\n");
pthread_mutex_lock(&mymutex1);
printf("wait in mythread2.\n");
pthread_cond_wait(&mycond,&mymutex1);
pthread_mutex_unlock(&mymutex1);
printf("end mythread2.\n");
return NULL;
}
void Dlg::OnBnClickedButton()
{
printf("begin main thread.\n");
int i;
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,mythread1,NULL);
pthread_create(&tid2,NULL,mythread2,NULL);
Sleep(200);
printf("try to wake up mythread1 and mythread2 in main thread.\n");
if(pthread_cond_broadcast(&mycond))
{
printf("error\n");
return ;
}
MessageBox(L"btn");
printf("end main thread.\n");
}
关于类的封装:
网上有很多人将线程封装为一个类,线程函数所以静态函数在类中封装,然后需要用的进行继承实现;
但是我觉得这样的封装虽然是面向对象的封装,但是在实际应用过程中,非常不友好,而且也不好用,再代码编写中不灵活,在代码阅读中增加了难度;对于简单的功能,过多的模式设计只会增加难度,让人难以理解;如果在一个具体的项目中可以根据项目的具体要求进行个性化设计,以增强代码效率,扩展,方便阅读,模块化等需求;
所以我简单封装一下,然后根据实际需要随时修改;
下面封装pthread类:
class CPthreadExitState
{
public:
CPthreadExitState()
{
m_tid = NULL;
m_mymutex = PTHREAD_MUTEX_INITIALIZER;
m_mycond = PTHREAD_COND_INITIALIZER;
}
CPthreadExitState( pthread_t * tid )
{
m_tid = NULL;
m_mymutex = PTHREAD_MUTEX_INITIALIZER;
m_mycond = PTHREAD_COND_INITIALIZER;
set_pthreadt( tid );
}
virtual ~CPthreadExitState()
{
m_tid = NULL;
m_mymutex = NULL;
m_mycond = NULL;
}
public:
void set_pthreadt( pthread_t * tid )
{
if (tid==NULL)
{
return ;
}
m_tid = tid;
}
public:
void set_pthread_eixt_state()
{
pthread_cond_signal(&m_mycond);
}
void wait_until_thread_exit_state()
{
pthread_mutex_lock( &m_mymutex);
pthread_cond_wait( &m_mycond, &m_mymutex );
pthread_mutex_unlock( &m_mymutex );
}
private:
pthread_t * m_tid;
pthread_mutex_t m_mymutex;
pthread_cond_t m_mycond ;
private:
bool m_bIsExitThread; //通常的线程都是由一个循环,和一个控制变量组成的,这里讲哲学基本的东西封装;
public:
void set_bIsExitThread( bool bIsExitThread )
{
m_bIsExitThread = bIsExitThread;
}
bool get_bIsExitThread()
{
return m_bIsExitThread;
}
};
class CPthreadWrap
{
public:
CPthreadWrap()
{
}
virtual ~CPthreadWrap()
{
}
public:
void create_thread( void *(PTW32_CDECL *start) (void *), void *arg )
{
m_ExitState.set_bIsExitThread( 1 );
pthread_create( &m_tid ,NULL, start, arg );
}
private:
pthread_t m_tid ;
public:
CPthreadExitState m_ExitState;
//这里简单封装几个关于CPthreadExitState的函数,也可以在外面手动写;
void set_ExitThread_WaitUntilThreadExitState()
{
m_ExitState.set_bIsExitThread( 0 );
m_ExitState.wait_until_thread_exit_state();
}
};
//应用示例:
void *mythread7(void *param)
{
if (param==NULL)
{
return 0;
}
CPthreadWrap * pCPthreadWrapObj = (CPthreadWrap*)param;
while( pCPthreadWrapObj->m_ExitState.get_bIsExitThread() )
{
static int n = 0;
std::cout<< "mythread7: " << n++ << std::endl;
Sleep(5000);
}
pCPthreadWrapObj->m_ExitState.set_pthread_eixt_state();
return NULL;
}
static CPthreadWrap CPthreadWrapObj;
void Ctmfc2Dlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码
CPthreadWrapObj.create_thread( mythread7, &CPthreadWrapObj );
//CPthreadWrapObj.m_ExitState.wait_until_thread_exit_state();
}
void Ctmfc2Dlg::OnBnClickedButton8()
{
// TODO: 在此添加控件通知处理程序代码
//CPthreadWrapObj.m_ExitState.set_bIsExitThread(0);//设置退出线程;
CPthreadWrapObj.set_ExitThread_WaitUntilThreadExitState(); //阻塞,知道线程退出;
MessageBox(L"ExitThread_WaitUntilThreadExitState OK");
}
示例的一点说明:
关于线程参数,这里我直接将封装类作为参数,但是在实际应用过程一般会将应用类和线程函数作为某个类的成员变量和静态成员函数,所以到时候将这个类作为参数传入,然后获取这里封装的pthrea类;
当然作为全局函数变量,和全局函数可以,但是不建议这么做;
或者,通过循环 sleep,判断变量,退出线程;Afxbeginthread的线程不可以这样判断;