【Linux高级环境编程】线程的创建

举报
ReCclay 发表于 2022/02/21 23:45:41 2022/02/21
【摘要】 文章目录 线程的创建一、restrict 关键字二、编译连接器的工作方式三、线程创建的例子四、等待线程的死亡五、线程的分离状态 线程的创建 pthread_create函数用于创建一个...


线程的创建

pthread_create函数用于创建一个线程

函数原型

#include<pthread.h>
int pthread_create(pthread_t *restrict tidp,
				const pthread_attr_t *restrict attr,
				void *(*start_rtn)(void *), 
				void *restrict arg);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

参数与返回值

  • tidp:类型为pthread_t的指针,当pthread_create成功返回时,该函数将线程ID存储在tidp指向的内存区域中,pthread_t:typedef unsigned long int pthread_t ,64位环境中是8字节无符号数,32位环境中是4字节无符号数。
  • attr:用于定制各种不同的线程属性。通常可设为NULL,采用默认线程属性
  • start_rtn:线程的入口函数,即新创建的线程从该函数开始执行。该函数只有一个参数,即arg,返回一个指针
  • arg:作为start_rtn的第一个参数
  • 成功返回0,出错时返回各种错误码

一、restrict 关键字

restrict关键字C99标准引入的,只能用于限定指针,表明指针是访问一个数据对象的唯一且初始的方式。概括的说,关键字restrict只用于限定指针;该关键字用于告知编译器,所有修改该指针所指向内容的操作全部都是基于该指针的,即不存在其它进行修改操作的途径;这样的后果是帮助编译器进行更好的代码优化,生成更有效率的汇编代码。

举个例子:

int ar[10];
int* restrict restar = (int *)malloc(10*sizeof(int));
int* par=ar;

for(int n=0; n<10; n++) 
{
   par[n]+=5;
   restar[n]+=5;
   ar[n]*=2;
   par[n]+=3;
   restar[n]+=3;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

即上述代码中,对于malloc分配的这段内存只能通过restar访问,并且restar[n] += 8 这样的操作编译器会进行优化,而par[n] += 8这样的操作不会进行优化。

实际上在C99标准出来以前,编译器就已经开始支持类似restrict的语义了,如编译器定义了__restrict。restrict关键词,实际上是用于指示编译器对代码进行优化的。最后注意一点,restrict是C99中定义的关键字,C++目前并未引入;在GCC可通过使用参数" -std=c99"来开启对C99的支持

下面是从C语言核心技术一书上摘的:
void *memcpy( void * restrict dest ,const void * restrict src,sizi_t n) 这是一个很有用的内存复制函数,由于两个参数都加了restrict限定,所以两块区域不能重叠,即 dest指针所指的区域,不能让别的指针来修改,即src的指针不能修改. 相对应的别一个函数 memmove(void *dest,const void * src,size_t)则可以重叠。

二、编译连接器的工作方式

代码3.2

  • 为什么程序会链接出错?
  • 如何改?
  • 如果为i加上const为如何?

三、线程创建的例子

代码3.3

  • 编译:g++ test.cpp –lpthread
  • 没有任何输出?
  • 其原因在于主线程先于新创建的线程退出
  • 什么是主线程?

怎么办?

  • 让主线程睡眠一段时间

四、等待线程的死亡

pthread_join函数用于等待某个线程终止,函数原型:

#include<pthread.h>
int pthread_join(pthread_t thread, 
				   void **rval_ptr);

  
 
  • 1
  • 2
  • 3

调用该函数的线程将一直阻塞,直到指定的线程退出。

int pthread_join(pthread_t thread,  void **rval_ptr);

  
 
  • 1

返回值与参数

  • 成功返回0,否则返回错误编号
  • thread:需要等待的线程ID
  • rval_ptr:返回线程的退出码若不关心线程返回值,可将该参数设置为NULL

代码3.4

五、线程的分离状态

在默认情况下,线程的终止状态会保存到对该线程调用pthread_join,若线程已经处于分离状态,线程的底层存储资源可以在线程终止时立即被收回。当线程被分离时,并不能用pthread_join函数等待它的终止状态,此时pthread_join返回EINVALpthread_detach函数可以使线程进入分离状态。

函数原型

#include<pthread.h>
int pthread_detach(pthread_t tid);

  
 
  • 1
  • 2

参数与返回值

  • tid:进入分离状态的线程的ID
  • 成功返回0,出错返回错误编号

示例3.5

pthread_joinpthread_detach先调用,也能获取到退出信息。

文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。

原文链接:recclay.blog.csdn.net/article/details/109607025

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。