POSIX多线程编程(一)
一、线程创建、启动
线程标识
每个进程拥有一个进程ID标识,线程对应的标识是线程ID和进程ID不同的是,进程ID在整个系统唯一,而线程ID只在所需进程中才有意义。线程ID使用phtread_t结构表示,因此不能把它当整数处理。在比较线程时,通过函数:
#include <pthread.h>
// 相同时返回非0,否则返回0
int pthread_equal(pthread_t tid1, pthread_t tid2);
// 获取线程自身ID
pthread_t pthread_self(void);
线程启动
传统UNIX进程中,每个进程有一个控制线程,可以认为正常程序启动后,任务在主线程中完成。可以通过pthread_create 新增线程,新增成功后返回0,否则返回错误码。线程启动后,便无法确定调用线程和新建线程的执行顺序了,因此创建后,要处理好调用线程和新建线程的竞争。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
void* thr_test(void* arg)
{
printf("hello!\n");
return 0;
}
int main(int argc, char* argv[])
{
pthread_t thid;
int err = pthread_create(&thid, NULL, thr_test, NULL);
if (err != 0)
{
printf("can't create thread!\n");
}
sleep(1); // 防止主线程直接退出,新线程还未执行
return 0;
}
C++编程多为面向对象的编程方式,很多时候启动线程在类中实现,当启动函数为类方法时,普通成员函数作为pthread_create的线程启动函数会出现参数问题,因为当把线程启动函数封装在类中时,this指针会作为默认参数传入到函数中,与线程启动函数的void*不能匹配。因此,要把线程启动函数声明为静态方法。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
class ThreadTest
{
public:
static void* run(void* arg)
{
printf("hello!\n");
return 0;
}
void start()
{
pthread_create(&m_thid, NULL, run, NULL);
}
int m_num;
pthread_t m_thid;
};
int main(int argc, char* argv[])
{
ThreadTest test;
test.start();
sleep(1);
return 0;
}
如上,便完成了通过成员函数启动。但是在类中,静态成员函数无法访问非静态成员变量和方法。这样,通过静态成员函数启动无法操作类成员,解决该问题,可以将this指针作为参数传递。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
// 线程创建函数仅支持void*一个参数,因为为传递多个参数,需要自定义结构
class ThreadTest
{
public:
static void* run(void* arg)
{
ThreadTest* pThis = (ThreadTest*)arg;
printf("hello, the number is %d!\n",pThis->m_num);
return 0;
}
void start()
{
pthread_create(&m_thid, NULL, run, (void*)this);
}
int m_num;
pthread_t m_thid;
};
int main(int argc, char* argv[])
{
ThreadTest test;
test.start();
sleep(1);
return 0;
}
ps:线程可以接受的启动函数中仅能传递一个参数,因此,想传递多个参数时,需要自己定义参数结构传输。