I 线程创建方法
1. 线程创建方法函数原型 : int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void*), void *arg);
2. pthread_create 方法的 4 个参数 ;
参数 1 ( pthread_t *tidp ) : 线程标识符指针 , 该指针指向线程标识符 ;
参数 2 ( const pthread_attr_t *attr ) : 线程属性指针 ;
参数 3 ( (void*)(*start_rtn)(void*) ) : 线程运行函数指针 , start_rtn 是一个函数指针 , 其参数和返回值类型是 void* 类型 ;
参数 4 ( void *arg ) : 参数 3 中的线程运行函数的参数 ;
3. 返回值说明 :
线程创建成功 , 返回 0 ;
线程创建失败 , 返回 错误代码 ;
4. 关于函数指针参数的说明 : C++ 中函数指针类型是 void *(PTW32_CDECL *start) (void *)
函数的参数类型是 void* 指针 ;
函数的返回值类型 void* 指针 ;
5. 函数多参数方案 : 如果线程执行的函数有多个参数 , 可以使用结构体 , 类进行封装 ;
6. 线程属性 : 创建线程时 , 给线程指定属性 pthread_attr_t 是结构体类型 ;
7. 代码示例 :
/* 线程创建方法函数原型 : int pthread_create( pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void*), void *arg); 该方法需要提供四个参数 ; 参数 1 ( pthread_t *tidp ) :线程标识符指针 , 该指针指向线程标识符 ; 参数 2 ( const pthread_attr_t *attr ) : 线程属性指针 ; 参数 3 ( (void*)(*start_rtn)(void*) ) : 线程运行函数指针 , start_rtn 是一个函数指针 , 其参数和返回值类型是 void* 类型 参数 4 ( void *arg ) : 参数 3 中的线程运行函数的参数 ; 返回值 : 线程创建成功 , 返回 0 ; 线程创建失败 , 返回 错误代码 ; 关于函数指针参数 : C++ 中函数指针类型是 void *(PTW32_CDECL *start) (void *) , 函数的参数类型是 void* 指针 函数的返回值类型 void* 指针 函数多参数方案 : 如果线程执行的函数有多个参数 , 可以使用结构体 , 类进行封装 线程属性 : 创建线程时 , 给线程指定属性 pthread_attr_t 是结构体类型 */ //函数指针 函数名 和 &函数名 都可以作为函数指针 pthread_create(&pid , &attribute, pthread_function, hello);
II 线程执行函数
1. 线程执行函数的要求 : C++ 中规定线程执行函数的函数指针类型是 void *(PTW32_CDECL *start) (void *) ;
2. 函数作用 : 将该函数的指针作为线程创建方法 pthread_create 的第三个参数 ;
3. 参数处理 : 在线程创建时 , 传入参数 , 将该参数转为 char* 字符串指针类型 , 将其打印出来 ;
4. 代码示例 :
/* 定义线程中要执行的方法 将该函数的指针作为线程创建方法 pthread_create 的第三个参数 C++ 中规定线程执行函数的函数指针类型是 void *(PTW32_CDECL *start) (void *) */ void* pthread_function(void* args) { //延迟 100 ms 执行 //_sleep(100); //指针类型转换 : 将 void* 转为 char* // 使用 static_cast 类型转换标识符 char* hello = static_cast<char*>(args); //打印参数 cout << "pthread_function 线程方法 执行 参数 : " << hello << endl; return 0; }
III 线程标识符
1. 线程标识符 : pthread_t 类型 , 用于声明线程的 ID ;
2. 类型本质 : 该类型是一个结构体 ;
typedef struct { void * p; /* Pointer to actual object */ unsigned int x; /* Extra information - reuse count etc */ } ptw32_handle_t; typedef ptw32_handle_t pthread_t;
3. 代码示例 : 声明线程标识符 , 下面的代码是在栈内存中声明线程标识符 , pthread_create 方法中需要传入指针 , 这里使用取地址符获取其指针 ;
//线程标识符 , 这里需要传入指针 , 因此这里使用 & 取地址符获取其地址当做指针变量 pthread_t pid;
IV 线程属性
1. 线程属性 : pthread_attr_t 表示线程属性类型 , 查看其类型声明 , 得到如下代码 , pthread_attr_t 类型是一个指针类型 ;
typedef struct pthread_attr_t_ * pthread_attr_t;
2. 线程属性声明 : 线程属性类型是一个指针 , 初始化时其值是随机值 , 是个野指针 , 这里将其设置为 0 ;
pthread_attr_t attribute = 0;
3. 线程属性的初始化和销毁 : 该线程属性需要先进行初始化和销毁;
① 线程属性初始化 : 函数原型 int pthread_attr_init(pthread_attr_t *attr); ; 初始化线程属性时 , 对属性进行了默认配置 ;
pthread_attr_init(&attribute);
② 线程属性销毁 : 函数原型 int pthread_attr_destroy(pthread_attr_t *attr); ;
//销毁线程属性 pthread_attr_destroy(&attribute);
4. 二维指针参数 :
① 参数说明 : 线程初始化和销毁方法传入 pthread_attr_t * 类型的参数 , pthread_attr_t 类型是指针 , pthread_attr_t * 是 二维指针 ; 初始化时 , 肯定要创建一个有实际意义的线程属性结构体 , 将 attribute 二维指针指向线程属性结构体指针 ;
② 指向指针的指针意义 : 在传递时可以 在函数内部 修改指针指向的地址 ;
5. 代码示例 :
/* 线程属性结构体变量 该线程属性需要先进行初始化和销毁; 线程属性初始化方法 : int pthread_attr_init(pthread_attr_t *attr); 线程属性销毁方法 : int pthread_attr_destroy(pthread_attr_t *attr); 线程属性类型定义 : typedef struct pthread_attr_t_ * pthread_attr_t; pthread_attr_t 其本质是一个指针 ; pthread_attr_t attribute 声明后 , 该指针是野指针 , 需要将其设置为 0 ; */ pthread_attr_t attribute = 0; //初始化线程属性, 此处的参数是指针的指针 , 该指针指向 0 地址 ; // 初始化时 , 肯定要创建一个有实际意义的线程属性结构体 , 将 attribute 二维指针 指向结构体指针 // 指向指针的指针意义 : 在传递时可以在函数内部修改指针指向的地址 ; //初始化线程属性时 , 对属性进行了默认配置 ; pthread_attr_init(&attribute);
V 线程属性 1 ( 分离线程 | 非分离线程 )
1. 线程的默认属性 : 线程创建后 , 默认是非分离线程 ;
2. 非分离线程 :
① 特点 : 非分离线程允许在其它线程中 , 来等待另外线程执行完毕 ;
② 表现 : 创建线程后 , 线程执行 , 如果调用 pthread_join 函数 , 其作用是等待 pthread_function 线程函数执行完毕 ;
3. 分离线程 : 不能被其它线程操作 , 如调用 pthread_join 函数 , 无法等待该分离线程执行完毕 ;
4. 非分离线程 与 分离线程 比较 :
① 设置非分离线程属性 : 先执行完线程内容 , 等待线程执行完毕后 , 才执行 pthread_join 后的代码 ;
② 设置分离线程属性 : pthread_join 等待线程执行完毕是无效的 , 主线程会继续向后执行 , 不会等待线程执行完毕
5. 分离线程不经常使用 : 一般情况下是不经常将线程设置为分离线程 , 如果设置了 , 那么该线程就无法进行控制 ;
6. 设置线程为分离线程代码示例 :
pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_DETACHED);