什么是线程
线程的定义
线程是一个程序中的运行流,有自己的内存空间和栈空间,并且同一个程序的线程之间的资源可以共享。
一个单一的线程可以包含多个线程,并且它们均属于同一个进程(程序)。这些线程共享相同的全局内存(包括内存空间和栈)。
线程的分离状态
线程的分离状态决定了线程以什么方式终止自己,通常我们创建的线程处于非分离状态,父线程需要通过pthread_join函数等待子线程的结束才可以释放自己的资源。而处于线程分离状态的线程则不需要父线程等待。
使用线程的优点和缺点
使用线程的优点就是可以使程序并行执行任务,而不必等待其他任务完成再执行。
使用线程的缺点是由于多个线程共享资源,所以如果处理不当可能会带来不可预期的问题。
怎么/何时使用线程
头文件:
#include <pthread.h>
需要的编译条件:
-pthread
所使用的函数:
函数原型 | 函数功能 |
int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr); | 对线程属性初始化/去除初始化 |
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); | 创建线程 |
int pthread_cancel(pthread_t thread); | 向线程发送终止信号 |
int pthread_detach(pthread_t thread); | 使线程进入分离态 |
int pthread_equal(pthread_t t1, pthread_t t2); | 比较两个线程的标识符 |
void pthread_exit(void *retval); | 使线程退出 |
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr); | 通过结构体初始化,用于明确指定线程属性 |
int pthread_join(pthread_t thread, void **retval); | 等待指定线程的结束 |
pthread_t pthread_self(void); | 返回线程当前的描述符 |
对线程属性进行初始化和去初始化
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
线程所具有的属性可保存在pthread_attr_t结构体中,要为线程指定属性必须首先对这个结构体进行初始化,使用完后需要注意去初始化。
参数说明:
pthread_attr_t记录了线程属性,结构体如下:
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
structsched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void* stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
The pthread_attr_t type should be treated as opaque: any access to the object other than via pthreads functions is nonportable and produces undefined results.
pthread_attr_t对象是不可见的,因此不可以直接改变其元素的值
从pthread_attr_t的元素中可以看出,可以通过设置该参数来配置线程的各种属性。
返回值:
执行成功返回0,失败返回一个非零的错误码。
下面例子展示将线程设置为分离态的方法:
#iinclude<pthread.h>
// 子线程
void *child_thread(void *arg)
{
printf(“child thread run!\n”);
}
int main(int argc,char *argv[ ])
{
pthread_ttid; // 线程ID
pthread_attr_tattr; // 线程属性
pthread_attr_init(&attr); // 初始化线程属性
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); // 修改线程属性为分离态
pthread_create(&tid,&attr,fn,arg); // 创建线程
pthread_attr_destroy(&attr); // 线程属性对象去初始化
sleep(1);
}
创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void (*start_routine) (void ), void *arg);
创建一个新的子线程
参数说明:
thread:创建线程的描述符
attr:线程属性
(*start_routine) (void ):线程的入口函数
*arg:入口函数的参数
返回值:
成功返回0,失败返回错误码,并且thread的内容未定义
终止线程
int pthread_cancel(pthread_t thread);
向指定的线程发送终止信号
参数说明:
thread:线程的描述符
返回值:
成功返回0,失败返回非零错误码
使线程进入分离态
int pthread_detach(pthread_t thread);
对已创建完成的线程进行分离
参数说明:
thread:线程的描述符
返回值:
成功返回0,失败返回错误码
对比线程描述符是否相同
int pthread_equal(pthread_t t1, pthread_t t2);
对比t1和t2是否使同一个线程
参数说明:
t1:要对比的第一个线程描述符
t2:要对比的第二个线程描述符
返回值:
如果两个描述符相同那么返回非零值,否则返回0
使线程退出
void pthread_exit(void *retval);
使线程退出
参数说明:
retval:函数的返回值,这个值可以被pthread_join函数接收到
等待线程的结束
int pthread_join(pthread_t thread, void **retval);
父线程将被堵塞等待线程的结束
参数说明:
thread:等待的线程描述符
retval:线程的结束返回值,通过pthread_exit返回或者return返回
返回值:
成功返回0,失败返回错误码。
获取当前线程的描述符
pthread_t pthread_self(void);
用于获取当前线程的线程描述符
返回值:
这个函数总是能成功执行的,返回当前线程的描述符。
Demo
#include <iostream>
#include <strings.h>
#include <pthread.h>
using namespace std;
char msg[64] = "hello i am work thread, this is my msg to you!";
void *work_thread(void *m)
{
int id = *(int*)m;
pthread_t thread_id = pthread_self();
cout << "hello i am work thread: " << thread_id << " and i will send a msg to father thread" << endl;
// pthread_exit((void *)&msg);
return msg;
}
int main(int argc, char *args[])
{
pthread_t thread_id;
int i = 9;
char *p = NULL;
cout << "hello this is a thread test program" << endl;
cout << "now i will create a thread!" << endl;
pthread_create(&thread_id, NULL, &work_thread, (void*)&i);
cout << "thread is created! now waitting for it exit!" << endl;
pthread_join(thread_id, (void**)&p);
cout << "thread is exit, and return a string: " << endl;
cout << "\t" << p << endl;
return 0;
}
程序输出:
- hello this is a thread test program
- now i will create a thread!
- thread is created! now waitting for it exit!
- hello i am work thread: 140184866203392 and i will send a msg to father thread
- thread is exit, and return a string:
- hello i am work thread, this is my msg to you!