在现实的计算机系统中,常常需要同时执行多个任务,比如多个用户同时访问一个网站,多个客户端同时请求服务器资源等。在这种情况下,单线程程序往往会出现响应缓慢、用户等待时间长等问题,因此需要使用多线程技术来提高程序的并发性能。
在Unix/Linux系统中,提供了一套强大的多线程编程接口,其中最常用的函数之一就是pthread_create。本文将详细介绍pthread_create函数的使用方法,包括其参数的含义、错误处理方式、典型应用场景等。
一、pthread_create函数概述
pthread_create函数用于创建一个新的线程,其原型如下:
```c
#include
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
```
参数解释:
1. *thread:指向pthread_t类型变量的指针,用于存放新线程的ID号,如果该指针为NULL,则新线程号将被忽略。
2. *attr:指向pthread_attr_t类型变量的指针,该参数用于设置线程的属性,如果为NULL,则使用默认属性。
3. *start_routine:线程功能函数指针,用于指定线程创建后所需执行的函数。
4. arg:传递给start_routine的参数。
pthread_create函数成功返回0,否则返回错误代码。
二、pthread_create函数参数详解
1. pthread_t *thread:
pthread_t是一个线程类型,其实际类型为unsigned long类型。在创建线程时,线程号将被存储在该变量中。调用pthread_create函数时需要传递一个指向pthread_t类型变量的指针,用于存储新线程的ID号。
示例代码如下:
```c
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
```
其中,tid为pthread_t类型变量,最后一个参数传递了NULL,表示没有参数传递给线程函数。
2. const pthread_attr_t *attr:
pthread_attr_t是线程属性类型,包含了线程的各种属性信息,比如线程栈大小、线程栈地址等。当创建线程时,可以通过该参数设置线程的属性。如不需要设置属性,则该参数可以传递NULL,使用默认属性。
示例代码如下:
```c
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024*1024); //指定线程栈大小为1MB
pthread_create(&tid, &attr, thread_func, NULL);
```
其中,attr为pthread_attr_t类型变量,演示代码中使用了pthread_attr_init和pthread_attr_setstacksize函数分别初始化线程属性和设置线程栈大小。
3. void *(*start_routine) (void *):
start_routine是一个函数指针,用于指定新线程将要执行的函数。函数指针的类型为void* (*)(void*),即返回值类型为void*,参数类型为void*。
示例代码如下:
```c
void* thread_func(void* arg)
{
//执行线程的实际功能代码
}
pthread_create(&tid, NULL, thread_func, NULL);
```
其中,thread_func为线程功能函数,用于执行指定线程的实际功能代码。
4. void *arg:
arg参数是传递给新线程的参数。类型为void*,可以传递任何类型的数据。示例代码如下:
```c
int a = 10;
pthread_create(&tid, NULL, thread_func, &a);
```
其中,&a表示将整型变量a的地址传递给线程函数。
三、pthread_create函数错误处理
pthread_create函数执行成功时返回0,否则返回错误代码。出错的可能原因包括线程资源不足、属性设置错误等。
如果pthread_create函数返回非0值(即出错),可以通过pthread_strerror函数进行错误信息的获取。示例代码如下:
```c
int ret = pthread_create(&tid, NULL, thread_func, NULL);
if(ret != 0)
{
char* errmsg;
pthread_strerror(ret, errmsg, 256); //将错误信息存储到errmsg中
printf("Error: %s", errmsg);
}
```
其中,pthread_strerror函数用于将错误信息存储到传递的缓冲区中,可以便于进一步进行处理或打印。
四、pthread_create函数应用实例
pthread_create函数广泛应用于多线程并发编程中。下面是一个简单的示例代码,展示了pthread_create函数的使用方式。
```c
#include
#include
int global = 0; //全局变量
void* thread_func(void* arg)
{
int local = *(int*)arg;
global++;
printf("Thread %d: global = %d, local = %d\n", pthread_self(), global, local);
pthread_exit(NULL);
}
int main()
{
int i, ret;
pthread_t tid[4];
int arg[4] = {1, 2, 3, 4}; //线程参数数组
for(i=0; i<4; i++)
{
ret = pthread_create(&tid[i], NULL, thread_func, (void*)&arg[i]);
if(ret != 0)
{
printf("Error creating thread %d.\n", i);
return -1;
}
}
for(i=0; i<4; i++)
{
ret = pthread_join(tid[i], NULL);
if(ret != 0)
{
printf("Error joining thread %d.\n", i);
return -1;
}
}
return 0;
}
```
该示例代码中创建4个新线程,每个线程执行thread_func函数,并打印全局变量global的值和传递给线程的参数值。为了避免竞争条件,每个线程在修改全局变量global前都会先+1,然后再进行打印操作。最后,等待所有线程执行完毕后,主线程退出。
五、总结
本文详细介绍了pthread_create函数的使用方法,包括其参数的含义、错误处理方式和典型应用场景等。同时,还给出了一个实际的示例代码,用于演示多线程编程中pthread_create函数的应用方式。通过本文的学习,相信大家对pthread_create函数有了更为深入的了解,可以在今后的多线程编程中更加准确、高效地使用pthread_create函数,提高程序的并发性能。