您的位置:首页 > 其它

pthread入门

2016-06-24 21:29 239 查看
pthread是linux下C语言执行多线程操作的基础,操作多线程的操作全部在pthread.h头文件中,因此想要创建一个线程并且操作线程的话,就需要引入头文件,跟线程密切相关的操作包括创建、退出以及主线程的等待(主线程一般是指main函数)

一、创建线程

int pthread_create(pthread_t* thread,pthread_attr_t* attr,void* (*start_routine)(void* arg),void* arg)


函数的第一个参数返回的是一个线程的指针,该指针唯一的标识创建的线程。

参数attr用来设置线程的属性,一般我们设置为NULL,即采用系统的默认设置。

第三个参数是线程将要执行的方法,或者说是线程的主体,该参数是一个函数指针,参数和返回值都是void*类型

第四个参数是第三个参数代表的方法所需要的参数

当创建线程成功时,该方法返回一个不为0的int

二、离开线程(销毁线程)

void pthread_exit(void* retval)


该方法离开该线程,并且返回一个指向某个对象的指针(该指针不能用来指向一个局部变量,因此离开线程之后,线程被销毁,资源被释放)

三、等待线程

在绝大多数情况下,我们需要在主线程中等待子进程的完成,然后执行后续操作,这样我们就需要pthread_join函数来完成任务。

int pthread_join(pthread_t t,void** thread_return)


该方法类似于fork中的wait,但不同的是,该方法面向的对象是线程而非进行,主线程会一直挂起,直到关注的子线程返回。

参数t表示关注的子线程的唯一标识

参数thread_return是一个void*值的地址,该参数得到的是线程的返回数据,即为pthred_exit中的参数值

四、DEMO

例子在主线程中创建一个线程,然后等待子线程的完成,并且在子线程中操作修改了一个全局变量message,然后等子线程返回后在重新调用message的值,程序的完成代码如下

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

void* thread_function(void* arg);
char message[]="hello world!\n";

int main(){

int res;
pthread_t a_thread;
void* thread_result;

res=pthread_create(&a_thread,NULL,thread_function,(void*)message);

if(res!=0){
printf("something wrong with the create thread\n");
exit(EXIT_FAILURE);
}

printf("waiting for thread to finish..\n");

res=pthread_join(a_thread,&thread_result);

/**
printf("res is %d\n",res);
**/
if(res!=0){
printf("something wrong with the join\n");
exit(EXIT_FAILURE);
}

printf("thread joined, it returns %s\n",(char*)thread_result);
printf("message now is %s\n",message);
exit(EXIT_SUCCESS);
}

void* thread_function(void* arg){
printf("thread function is now runing1,the argument is %s\n",(char*)arg);
sleep(3);
strcpy(message,"Bye");
pthread_exit("Thank you for the CPU time!\n");
}


注:linux下编译此程序需要执行下面的shell脚本

gcc simpleThread.c -o simpleThread -lpthread


程序的运行结果如下所示



备注:

在该段代码中,我们的共享变量是char[]类型,如果我们把message的类型改成char*,那么这段代码在运行的时候会发生段错误,因为char*指向的是一段常量字符串,该值不可被改变,但是char[]所表示的指针指向一段数组,只要不越界,就可进行操作,这里有一个很经典的笔试题

char* s1="hi";
char* s2="hi";
char s3[]="hi";
char s4[]="hi";


s1==s2,s3!=s4

同样,我们可以考虑一下c++ stl库中的string类型,在其内部究竟是维护了一个char*类型还是char[]类型?

当然是char[],但是用char*去特指,即在创建的时候申请一个char数组,然后把数组指针赋给char*,那么我们在对字符串进行扩容或者执行+操作是,肯定会额外再去申请一段数组,因此如果我们把数组的大小,使用程度存储起来的话,就能在一定程度上减少申请操作,这就是动态字符串的原理,redis等kv数据库均采用这种方法存储字符串
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: