文章目录 pthread_equal() 线程参数传递 传递指针 传递整型参数 方式一:直接强制转换 方式2:使用 intptr_t / uintptr_t(C99标准推荐) 方式3:为单个整数动态分配内存 传递复杂数据 方式1:定义结构体 方式2:为每个线程动态分配独立结构 传参选择依据 pthread_equal() POSIX标准只定义了线程相关数据类型的接口行为,没有规定其内部实现。在不同的操作系统或架构上:pthread_t 可能是:unsigned long(Linux x86_64)、结构体指针(某些BSD系统)、整数索引等 互斥锁、条件变量等可能有不同的内部布局 pthread_equal() 是 Pthreads 标准中专门用于比较两个线程 ID(pthread_t 类型)是否相等的函数,解决了 pthread_t 类型跨平台兼容性问题(避免直接用 == 比较的风险) “不透明”的数据类型: 数据类型 描述 pthread_t 线程 ID pthread_mutex_t 互斥对象(mutex) pthread_mutexattr_t 互斥属性对象 pthread_cond_t 条件变量(condition variable) pthread_condattr_t 条件变量的属性对象 pthread_key_t 线程特有数据的键(Key) pthread_once_t 一次性初始化控制上下文(control context) pthread_attr_t 线程的属性对象
函数原型 # include <pthread.h> int pthread_equal ( pthread_t t1, pthread_t t2) ; 参数 要比较的线程 ID,如pthread_self()返回值、pthread_create输出的 ID 返回值 非 0 值:t1 和 t2 指向同一个线程 0:两个线程 ID 不相等 // 错误:不可移植 if ( tid1== tid2) { . . . } // 正确:可移植 if ( pthread_equal ( tid1, tid2) != 0 ) { . . . } // 检查当前线程是否是特定线程 if ( pthread_equal ( pthread_self ( ) , main_thread_id) != 0 ) { // 这是主线程 } 线程参数传递 线程参数传递主要涉及两种方式:传递指针:传递变量的地址(或字符串常量地址) 传递整数值:将整数值直接转换为指针传递 传递指针 # include <pthread.h> # include <stdio.h> # include <stdlib.h> # include <errno.h> void * func ( void * arg) { char * str= ( char * ) arg; printf ( "%s\n" , str) ; pthread_exit ( NULL ) ; } int main ( int argc, const char * argv[ ] ) { pthread_t tid; char * str= "Hello Thread!" ; int ret= pthread_create ( & tid, NULL , func, str) ; if ( ret!= 0 ) { errno= ret; perror ( "pthread_create" ) ; exit ( EXIT_FAILURE) ; } ret= pthread_join ( tid, NULL ) ; if ( ret!= 0 ) { errno= ret; perror ( "pthread_create" ) ; exit ( EXIT_FAILURE) ; } return 0 ; } 优点 可以传递任意复杂的数据结构 传递效率高(只传指针,不拷贝数据) 符合 void* 指针的设计初衷 注意事项 数据生命周期管理 // 危险:传递局部变量的地址 void create_thread ( ) { char buffer[ 64 ] ; // 栈上分配 sprintf ( buffer, "Thread data" ) ; pthread_create ( & tid, NULL , func, buffer) ; // 函数返回时buffer被释放,但线程可能还在访问! } // <- 这里buffer的栈内存被回收! // 安全做法1:传递全局/静态变量 static char buffer[ 64 ] ; // 或全局变量 void create_thread ( ) { sprintf ( buffer, "Thread data" ) ; pthread_create ( & tid, NULL , func, buffer) ; } // 安全做法2:动态分配 void create_thread ( ) { char * buffer= malloc ( 64 ) ; sprintf ( buffer, "Thread data" ) ; pthread_create ( & tid, NULL , func, buffer) ; // 在线程函数中必须free! } // 安全做法3:传递字符串常量(只读段) pthread_create ( & tid, NULL , func, "Constant string" ) ; 多线程并发访问 // 危险:多个线程共享同一数据指针 int shared_data= 0 ; for ( int i= 0 ; i< 5 ; i++ ) { // 所有线程都收到 &shared_data 的指针 pthread_create ( & tids[ i] , NULL , func, & shared_data) ; } // 线程间会竞争修改shared_data,需要同步机制! 传递整型参数 方式一:直接强制转换 # include <pthread.h> # include <stdio.h> # include <stdlib.h> # include <errno.h> void * func ( void * arg) { printf ( "arg:%d\n" , ( int ) arg) ; pthread_exit ( NULL ) ; } int main ( int argc, const char * argv[ ] ) { pthread_t tid; int a= 10 ; int ret= pthread_create ( & tid, NULL , func, a) ; if ( ret!= 0 ) { errno= ret; perror ( "pthread_create" ) ; exit ( EXIT_FAILURE) ; } ret= pthread_join ( tid, NULL ) ; if ( ret!= 0 ) { errno= ret; perror ( "pthread_create" ) ; exit ( EXIT_FAILURE) ; } return 0 ; } 可以工作但是编译会报警告:可移植性问题:如果int和指针大小不同(如int是32位,指针是64位),转换可能丢失精度 类型安全问题:绕过了类型系统,编译器无法检查 标准未定义:C标准不保证这种转换的行为 严格说来,对于int与void*之间相互强制转换的后果,C语言标准并未加以定义。不过,大部分C语言编译器允许这样的操作,并且也能达成预期的目的 方式2:使用 intptr_t / uintptr_t(C99标准推荐) # include <stdint.h> // 包含intptr_t的定义 // 传递 int a= 10 ; pthread_create ( & tid, NULL , func, ( void * ) ( intptr_t ) a) ; // 接收 void * func ( void * arg) { int value= ( int ) ( intptr_t ) arg; // 先转intptr_t,再转int } C99标准定义的有符号整数类型intptr_t,保证可以安全地存储指针值(转换为整数再转回指针不变) 大小与指针相同,解决了可移植性问题 方式3:为单个整数动态分配内存 // 传递 int * p= malloc ( sizeof ( int ) ) ; * p= 10 ; pthread_create ( & tid, NULL , func, p) ; // 在线程函数中free(p) // 接收 void * func ( void * arg) { int value= * ( int * ) arg; free ( arg) ; // 得释放! // ... } 传递复杂数据 方式1:定义结构体 typedef struct { int id; const char * name; int priority; void * device_handle; } ThreadParams; // 传递 ThreadParams params= { 1 , "SensorReader" , 10 , dev_handle} ; pthread_create ( & tid, NULL , sensor_thread, & params) ; // 注意:params必须是全局的或动态分配的 // 如果params是局部变量,确保线程在函数返回前已使用完数据 方式2:为每个线程动态分配独立结构 for ( int i= 0 ; i< NUM_THREADS; i++ ) { ThreadParams* params= malloc ( sizeof ( ThreadParams) ) ; params-> id= i; params-> name= thread_names[ i] ; params-> priority= priorities[ i] ; pthread_create ( & tids[ i] , NULL , worker_thread, params) ; // 在线程函数中free(params) } 传参选择依据 数据类型 推荐方法 代码示例 注意事项 字符串常量 直接传递 pthread_create(..., "string")只读,安全 单个整数 intptr_t转换(void*)(intptr_t)value可移植,简洁 单个指针 直接传递 (void*)&data注意生命周期 多个参数 结构体指针 (void*)¶ms结构体需全局或动态分配 大量数据 传递数据指针 (void*)large_buffer考虑拷贝开销 vs 共享风险