pthread(POSIX thread),简称为pthread,是线程的POSIX标准,在类Unix操作系统中(Unix、Linux、Mac OS X等),都是用pthread作为操作系统的线程。
pthread_create
是UNIX环境创建线程函数 。共四个参数:
pthread_t*
(void*)(*)(void*)
void *
无参数函数
pthread_create
创建线程执行无参数函数的demo。
#include
#include
using namespace std;
// 注意函数定义: void* (*)(void*)
void* test(void *ptr){
cout << "hello world." << endl;
}
int main()
{
pthread_t tid; // 声明线程id typedef unsigned
pthread_create(&tid, NULL, test, NULL); // 创建线程
pthread_join(tid, NULL);
}
带参数函数
pthread_create
只支持单个指针,只能传一个参数;如果要传多个参数,封装成结构体形式。
#include
#include
#include
using namespace std;
struct Param{
string name;
int age;
};
void* param_test(void* p){
Param *param = (Param*)p;
cout << "hello " << param->name << endl;
cout << "age = " << param->age << endl;
}
int main()
{
pthread_t tid;
Param *ptr = new Param();
ptr->name = "pthread";
ptr->age = 20;
pthread_create(&tid, NULL, param_test, ptr);
pthread_join(tid, NULL);
}
类成员函数
调用类成员函数的方式有点复杂,需要另外一个函数封装,函数参数显式传入类实例指针,之后便与调用带参数函数的方法类似。
#include
#include
#include
using namespace std;
class PthreadClass{
public:
void say_hello(){
cout << "hello world" << endl;
}
};
// 封装 传入类实例指针
void* class_test(void *p){
PthreadClass *ptr = (PthreadClass*)p;
// 实例调用
ptr->say_hello();
}
int main()
{
PthreadClass *ptr = new PthreadClass();
pthread_t tid;
pthread_create(&tid, NULL, class_test, ptr);
pthread_join(tid, NULL);
}
pthread_join
用来等待一个线程的结束,线程间同步的操作 ,共两个参数:
pthread_t
type: void**
#include
#include
using namespace std;
class PthreadClass{
public:
void say_hello(){
cout << "hello world" << endl;
}
};
int retval = -1;
void* class_test(void *p){
PthreadClass *ptr = (PthreadClass*)p;
ptr->say_hello();
retval = 0;
return (void*)&retval;
}
int main()
{
PthreadClass *ptr = new PthreadClass();
pthread_t tid;
pthread_create(&tid, NULL, class_test, ptr);
/**
* 等待结束
* 注意,如果不加pthread_join,那么有可能新线程还没等创建出来就已经结束程序
*/
void *retval;
pthread_join(tid, &retval);
cout << *(int*)retval << endl;
}
创建一个线程默认的状态是joinable
, 如果一个线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收(退出状态码),所以创建线程者应该pthread_join
来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于wait,waitpid)。
但是调用pthread_join
后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此,比如在Web服务器中当主线程为每个新来的链接创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的链接),这时可以在子线程中加入代码pthread_datach
脱离阻塞,这时候子线程状态为detached
,运行结束后会自动释放资源。
pthread_detach
只有一个参数:
pthread_t
#include
#include
#include
using namespace std;
void* test(void *p){
sleep(1000);
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, test, NULL);
pthread_detach(tid);
for(int i = 0; i < 1000; i ++){
sleep(1);
cout << "sleep " << i << " second." << endl;
}
}
这里使用pthread_detach
,就不会阻塞在test
的sleep
内,会跑进for
循环,如果使用的是pthread_join
的话,则会等到test
函数运行完毕才会往下跑。
pthread_self
函数无参数,作用是获取当前线程id
。
#include
#include
#include
using namespace std;
void* test(void *p){
cout << 'child thread: ' << pthread_self() << endl;
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, test, NULL);
pthread_detach(tid);
cout << 'main thread: ' << pthread_self() << endl;
for(int i = 0; i < 1000; i ++){
sleep(1);
}
}
以上代码会输出,主线程和子线程不同的线程id:
main thread: 1
child thread: 2
pthread_once
在多线程环境中只执行一次,将多线程环境中只需要执行一次的操作交给 pthread_once
执行,则会线程安全的只执行一次。
pthread_once
有两个参数:
pthread_once_t
变量,相当于标识符,type: pthread_once_t
void(*func)(void)
以下例子,once_run
只会执行一次,但每次执行的结果可能不同,once_run
可能在线程1执行,也可能在线程2执行。
#include
#include
#include
using namespace std;
pthread_once_t once = PTHREAD_ONCE_INIT;
void once_run(void)
{
cout<<"once_run in thread "<<(unsigned int )pthread_self()<
输出:
thread 2 enter
once_run in thread 2
thread 2 return
thread 3 enter
thread 3 return
发送一个cancel
信号给指定线程,只有一个参数线程标识符,类型为pthread_t
,用法简单,这里不多做介绍,要了解原理的同学可以在linux下用man命令了解更多。
man pthread_cancel
向某个线程传递一个信号 ,需要在创建的线程中使用signal(SIGKILL,sig_handler)
函数处理信号,如果你给一个线程发送了SIGQUIT
,但线程却没有实现signal处理函数,则整个进程退出。
pthread_kill
两个参数:
pthread_t
int