pthread_create函数的详细讲解(包括向线程函数传递参数详解)

本文详细介绍了UNIX环境下pthread_create函数的使用方法,包括函数原型、参数说明、返回值及示例代码。同时,还提供了如何向线程函数传递参数的具体示例。

http://blog.youkuaiyun.com/liangxanhai/article/details/7767430

pthread_create是UNIX环境创建线程函数

头文件

  #include<pthread.h>

函数声明

  int pthread_create(pthread_t*restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);

返回值

  若成功则返回0,否则返回出错编号
  返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于制定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个万能指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。
  linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。
  由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。

参数

  第一个参数为指向线程标识符的指针。
  第二个参数用来设置线程属性。
  第三个参数是线程运行函数的起始地址。
  最后一个参数是运行函数的参数。
  另外,在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库

示例

  打印线程 IDs
  #include <pthread.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <string.h>
  pthread_t ntid;
  void printids(const char *s)
  {
  pid_t pid;
  pthread_t tid;
  pid = getpid();
  tid = pthread_self();
  printf("%s pid %u tid %u (0x%x)\n", s,
  (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);
  } void *thr_fn(void *arg)
  {
  printids("new thread: ");
  return((void *)0);
  }
  int main(void)
  {
  int err;
  err = pthread_create(&ntid, NULL, thr_fn, NULL);
  if (err != 0)
  printf("can't create thread: %s\n", strerror(err));
  printids("main thread:");
  sleep(1);
  exit(0);
  }
  $ gcc main.c -lpthread

  $ ./a.out

向线程函数传递参数详解:

向线程函数传递参数分为两种:

(1)线程函数只有一个参数的情况:直接定义一个变量通过应用传给线程函数。

例子:

#include <iostream>
#include <pthread.h>
using namespace std;
pthread_t thread;
void fn(void *arg)
{
    int i = *(int *)arg;
    cout<<"i = "<<i<<endl;
    return ((void *)0);
}
int main()
{
    int err1;
    int i=10;
   err1 = pthread_create(&thread, NULL, fn, &i);
    pthread_join(thread, NULL);
}
2、线程函数有多个参数的情况:这种情况就必须申明一个结构体来包含所有的参数,然后在传入线程函数,具体如下:

例子:

首先定义一个结构体:

struct  parameter

{

  int size,

  int count;

。。。。。

。。。 
};

然后在main函数将这个结构体指针,作为void *形参的实际参数传递

struct parameter arg;

通过如下的方式来调用函数:
pthread_create(&ntid, NULL, fn,& (arg));
函数中需要定义一个parameter类型的结构指针来引用这个参数 

void fn(void *arg)
{
    int i = *(int *)arg;
    cout<<"i = "<<i<<endl;
    return ((void *)0);
}

void thr_fn(void *arg)
{
       struct parameter *pstru;
       pstru = ( struct parameter *) arg;
       然后在这个函数中就可以使用指针来使用相应的变量的值了。
}
<think>嗯,用户想了解pthread_create函数参数,需要详细讲解每个参数的作用和用法。首先,我得回忆一下这个函数参数结构。pthread_create是POSIX线程库中创建线程函数,对吧?它的函数原型是int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)。总共有四个参数,对吧? 第一个参数pthread_t类型的指针,用来保存新线程的标识符。用户可能想知道这个参数是传入一个指针,函数内部会填充线程ID。需要说明这个参数的作用,比如成功创建后,线程ID存储在这里。 第二个参数pthread_attr_t类型的指针,指向线程属性结构体。用户可能对线程属性不太熟悉,需要解释这个参数的作用,比如设置栈大小、调度策略等,如果为NULL则使用默认属性。可能还需要提到,大多数情况下用NULL即可,除非有特殊需求。 第三个参数线程函数函数指针,这个函数应该接受一个void*参数并返回void*。这里可能需要详细说明,比如线程启动后会执行这个函数函数必须符合这个签名。用户可能对如何传递参数给这个函数有疑问,所以第四个参数应该和第三个相关。 第四个参数传递线程函数参数,类型是void*。需要说明如何将需要传递的数据强制转换为void*,然后在线程函数内部再转换回来。例如,传递一个结构体指针或者简单的整型。同时要提醒用户注意数据生命周期的管理,避免传递局部变量的地址而导致问题。 然后,返回值方面,pthread_create返回0表示成功,非0表示错误码。用户可能需要处理错误情况,比如用strerror输出错误信息。 用户可能的疑问包括如何传递多个参数线程函数,这时候可能需要建议使用结构体封装多个数据。或者线程属性的具体设置方法,这时候可以简要提及使用pthread_attr_init和相关函数,但详细说明可能超出当前问题范围。 另外,用户可能是在学习多线程编程的基础,需要确保示例代码清晰,比如展示一个简单的创建线程的例子,传递一个整数或字符串,并展示如何在线程函数中处理。 需要避免哪些常见的错误?比如忘记检查返回值,或者在传递参数时使用了无效的指针。还要注意线程之间的资源竞争,但可能不属于参数讲解的重点。 总结下来,应该分点解释四个参数,每个参数的类型、作用、用法示例,以及常见注意事项。确保用中文解释清楚,避免术语混淆,必要时提供代码示例片段帮助理解。`</think>pthread_create` 是 POSIX 线程库中用于创建线程函数,其参数定义了线程的行为和资源。以下是它的参数详解: --- ### **函数原型** ```c int pthread_create( pthread_t *thread, // 参数1:线程标识符指针 const pthread_attr_t *attr,// 参数2:线程属性指针 void *(*start_routine)(void*), // 参数3:线程函数指针 void *arg // 参数4:传递线程函数参数 ); ``` --- ### **参数详解** #### **1. `pthread_t *thread`** - **作用**:用于存储新线程的标识符(ID)。 - **用法**: - 传入一个 `pthread_t` 类型变量的地址,线程创建成功后,系统会将线程 ID 写入该变量。 - 后续可通过此 ID 操作线程(如 `pthread_join` 等待线程结束)。 - **示例**: ```c pthread_t tid; // 定义线程 ID pthread_create(&tid, NULL, thread_func, NULL); // 创建线程,ID 存入 tid ``` --- #### **2. `const pthread_attr_t *attr`** - **作用**:设置线程的属性(如栈大小、调度策略等)。 - **用法**: - 传入 `NULL` 表示使用默认属性。 - 若需自定义属性,需先通过 `pthread_attr_init` 初始化属性对象,再通过 `pthread_attr_set*` 函数设置。 - **示例**(设置线程为分离状态): ```c pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 分离线程 pthread_create(&tid, &attr, thread_func, NULL); pthread_attr_destroy(&attr); // 销毁属性对象 ``` --- #### **3. `void *(*start_routine)(void*)`** - **作用**:线程启动后执行的函数。 - **用法**: - 函数必须符合签名:`void* function_name(void *arg)`。 - 线程会独立运行此函数函数返回时线程结束。 - **示例**: ```c void* thread_func(void *arg) { printf("Thread is running!\n"); return NULL; } pthread_create(&tid, NULL, thread_func, NULL); ``` --- #### **4. `void *arg`** - **作用**:传递线程函数参数。 - **用法**: - 将参数强制转换为 `void*` 类型传入,在线程函数内部再转换回原始类型。 - 可传递简单值(如 `int`)、结构体指针或动态分配的内存。 - **示例**(传递整数): ```c void* thread_func(void *arg) { int num = *(int*)arg; printf("Received: %d\n", num); return NULL; } int main() { int value = 42; pthread_create(&tid, NULL, thread_func, &value); // 传递 value 的地址 // 注意:需确保 value 在线程运行时有效(避免传递局部变量后立即退出) } ``` --- ### **返回值** - **成功**:返回 `0`。 - **失败**:返回错误码(非零值),可通过 `strerror(errno)` 获取错误信息。 --- ### **注意事项** 1. **参数生命周期**:若传递局部变量的地址,需确保线程运行时变量未被销毁。 2. **线程安全**:多线程共享数据时需使用互斥锁(`pthread_mutex`)避免竞争。 3. **资源释放**:若传递动态内存(如 `malloc`),需在线程内释放或在主线程中等待线程结束。 --- ### **完整示例** ```c #include <stdio.h> #include <pthread.h> typedef struct { int id; char *msg; } ThreadArgs; void* thread_func(void *arg) { ThreadArgs *args = (ThreadArgs*)arg; printf("Thread %d: %s\n", args->id, args->msg); free(args); // 释放动态分配的结构体 return NULL; } int main() { pthread_t tid; ThreadArgs *args = malloc(sizeof(ThreadArgs)); args->id = 1; args->msg = "Hello from thread!"; if (pthread_create(&tid, NULL, thread_func, args) != 0) { perror("Failed to create thread"); return 1; } pthread_join(tid, NULL); // 等待线程结束 return 0; } ``` 通过合理使用参数,可以灵活控制线程的行为和数据传递
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值