接口
pthread_create()线程创建
- pthread_t* thread:输出型参数,将线程的tid值放入到我们外部创建好的pthread_t 类型的变量中。
- const pthread_attr_t *attr:用来设置线程属性,一般情况下设置成nullptr,等用到的时候再详细讲解。
- void* (*start_routine)(void *):函数指针,这是一个回调函数,该函数的内容就是新线程要执行的。
- void* arg:回到函数的参数。
- 返回值: 线程创建成功返回0,不成功返回错误码。
cpp
#include<iostream>
#include<unistd.h>
#include<pthread.h>
using namespace std;
#define NUM 10
void* test(void* args)
{
sleep(1);
string name = (char*) (args);
while(1)
{
cout << "new thread name:" << name << endl;
sleep(1);
}
}
int main()
{
for (int i = 0; i < NUM; i ++)
{
pthread_t tid;
char buffer[64];
snprintf(buffer, sizeof buffer, "thread %d", i+1);
pthread_create(&tid, nullptr, test, (void*)buffer);
}
while(1)
{
cout << "create success..." << endl;
sleep(1);
}
return 0;
}
运行结果如下:
为什么会导致这样的结果?
观察上面主线程创建子线程的时候,我们在for循环里定义了buffer缓冲区,然后将线程的名字打印进buffer中。
理想的结果是打印thread 1, thread 2, thread3...但是结果是只打印了thread10。
原因:
1、buffer的生命周期在for循环内部,当跳出循环的时候buffer就消失了,新创建的buffer会继续在上一个buffer的地址位置创建新的buffer。
2、因为buffer生命周期的原因,并且pthread_create传递的是buffer的地址,所以,其实所有的线程拿到的是同一个缓冲区。pthead 1,phtead2等等会被后面的线程覆盖,最后都变成pthread10。
所以,为了让所有的线程都有自己的缓冲区,可以new一个空间给每个空间。避免了生命周期的问题。
1、解决方法一
2、解决方法二
使用类,将内容写入到每个线程的类中。
执行结果:
pthread_exit()结束线程
- 参数:返回线程结束信息,当前阶段设置成nullptr即可。
执行结果:
pthread_join()线程等待函数
和进程等待一样,将线程回收,避免内存泄漏
- pthread_t thread:要等待的线程tid。
- void** retval:线程结束信息返回,这是一个输出型参数。
- 返回值:等待成功返回0,等待失败返回错误码。
运行结果:
线程等待返回值
运行结果:
所以,可以通过线程等待的返回值判断线程是不是正常退出。
pthread_canel()取消线程
pthread_self()查看线程tid
查看线程自己的tid,和查看进程的pid一样,接口是pthread_join
作用就是查看调用该函数的线程的tid
pthead_detach()线程分离
从上面的各种结果可以看出,线程等待是阻塞等待。
按道理说,应该是主线程边打印,子线程边进行。但是程序执行的结果表示,子线程执行完了再执行主线程的内容。
当主线程不关注子线程的退出情况的时候,阻塞等待就现得很没用。所以,我们可不可以不进行阻塞等待呢?
可以。
返回值:成功返回0,失败返回错误码
一个线程不能既是joinable,又是分离的**。将线程设置为分离的之后,主线程将不再关心线程的退出状态,子线程会自动释放**。
线程分离之后再进行线程等待会失败
cpp
void* test(void* args)
{
sleep(1);
char *name = (char*)args;
//进行线程分离
pthread_detach(pthread_self());
int cnt = 5;
while(cnt--)
{
cout << "new thread name:" << name << endl;
sleep(1);
}
return (void*) 1;
}
int main()
{
pthread_t tid;
pthread_create(&tid, nullptr, test, (void *)"thread one");
int n = pthread_join(tid, nullptr);
cout << "join pthread -> " << strerror(n) << endl;
return 0;
}
执行结果:
线程等待成功
不是说线程分离了再进行线程等待就会失败吗?怎么上面的运行结果仍然是等待成功呢?
因为主线程先被调度,在新线程被创建但是没有执行的时候主线程就开始等待新线程了。
所以当新线程将自己分离以后,主线程已经处于等待状态了,它不认为新线程被分离,还会继续等待,而且可以等待成功。
如果让主线程先等待一会儿,让新线程先执行,就可以看到线程等待失败
执行结果:
正确的做法:在主线程中分离新线程
cpp
void* test(void* args)
{
sleep(1);
char *name = (char*)args;
int cnt = 5;
while(cnt--)
{
cout << "new thread name:" << name << endl;
sleep(1);
}
return (void*) 1;
}
int main()
{
pthread_t tid;
cout << "主线程tid: " << pthread_self() << endl;
pthread_create(&tid, nullptr, test, (void *)"thread one");
pthread_detach(tid);
int n = pthread_join(tid, nullptr);
cout << "join pthread -> " << strerror(n) << endl;
while(1)
{
cout << "主线程..." << endl;
sleep(1);
}
return 0;
}
这样做的好处是,在主线程等待失败之后,主线程并不会阻塞。从后来一直打印"主线程..."这里可以看出来。