由于实验需要,需要了解下C语言多线程编程的知识,于是学习了下POSIX线程编程的知识,有点心得,记录并分享一下。

POSIX(可移植操作系统接口)线程是提高代码响应和性能的有力手段。与标准 fork() 相比,线程带来的开销很小。内核无需单独复制进程的内存空间或文件描述符等等。这就节省了大量的 CPU 时间,使得线程创建比新进程创建快上十到一百倍。分析一个简单的POSIX线程例子:

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void *thread_function(void *arg) {
int i;
for ( i=0; i<20; i++) {
printf("Thread says hi!\n");
sleep(1);
}
return NULL;
}
int main(void) {
pthread_t mythread; if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
printf("error creating thread.");
abort();
}
if ( pthread_join ( mythread, NULL ) ) {
printf("error joining thread.");
abort();
}
exit(0);
} main() 中声明了变量 mythread,类型是 pthread_t。pthread_t 类型在 pthread.h 中定义,通常称为“线程 id”(缩写为 "tid")。可以认为它是一种线程句柄。
mythread 声明后(记住 mythread 只是一个 "tid",或是将要创建的线程的句柄),调用 pthread_create 函数创建一个真实活动的线程。不要因为 pthread_create()
在 "if" 语句内而受其迷惑。由于 pthread_create() 执行成功时返回零而失败时则返回非零值,将 pthread_create() 函数调用放在 if() 语句中只是为了方便地检测
失败的调用。让我们查看一下 pthread_create 参数。第一个参数 &mythread 是指向 mythread 的指针。第二个参数当前为 NULL,可用来定义线程的某些属性。由于缺省
的线程属性是适用的,只需将该参数设为 NULL。 第三个参数是新线程启动时调用的函数名。本例中,函数名为 thread_function()。当 thread_function() 返回时,新线程将终止。本例中,线程函数没有实现大的功能。
它仅将 "Thread says hi!" 输出 20 次然后退出。注意 thread_function() 接受 void * 作为参数,同时返回值的类型也是 void *。这表明可以用 void * 向新线
程传递任意类型的数据,新线程完成时也可返回任意类型的数据。那如何向线程传递一个任意参数?很简单。只要利用 pthread_create() 中的第四个参数。本例中,因为没有
必要将任何数据传给微不足道的 thread_function(),所以将第四个参数设为 NULL。

您也许已推测到,在 pthread_create() 成功返回之后,程序将包含两个线程。等一等, 两个线程?我们不是只创建了一个线程吗?不错,我们只创建了一个进程。但是主程序同样也是一个线程。可以这样理解:如果编写的程序根本没有使用 POSIX 线程,则该程序是单线程的(这个单线程称为“主”线程)。创建一个新线程之后程序总共就有两个线程了。

我想此时您至少有两个重要问题。第一个问题,新线程创建之后主线程如何运行。答案,主线程按顺序继续执行下一行程序(本例中执行 "if (pthread_join(...))")。第二个问题,新线程结束时如何处理。答案,新线程先停止,然后作为其清理过程的一部分,等待与另一个线程合并或“连接”。

现在,来看一下 pthread_join()。正如 pthread_create() 将一个线程拆分为两个, pthread_join() 将两个线程合并为一个线程。pthread_join() 的第一个参数是 tid mythread。第二个参数是指向 void 指针的指针。如果 void 指针不为 NULL,pthread_join 将线程的 void * 返回值放置在指定的位置上。由于我们不必理会 thread_function() 的返回值,所以将其设为 NULL.

您会注意到 thread_function() 花了 20 秒才完成。在 thread_function() 结束很久之前,主线程就已经调用了 pthread_join()。如果发生这种情况,主线程将中断(转向睡眠)然后等待 thread_function() 完成。当 thread_function() 完成后, pthread_join() 将返回。这时程序又只有一个主线程。当程序退出时,所有新线程已经使用 pthread_join() 合并了。这就是应该如何处理在程序中创建的每个新线程的过程。如果没有合并一个新线程,则它仍然对系统的最大线程数限制不利。这意味着如果未对线程做正确的清理,最终会导致 pthread_create() 调用失败。

pthread_join函数简介

函数pthread_join用来等待一个线程的结束。
头文件 : #include <pthread.h>
函数定义: int pthread_join(pthread_t thread, void **retval);
描述 :
pthread_join()函数,以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果进程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。
参数 :
thread: 线程标识符,即线程ID,标识唯一线程。
retval: 用户定义的指针,用来存储被等待线程的返回值。

返回值 : 0代表成功。 失败,返回的则是错误号。

pthread_join的应用

pthread_join使一个线程等待另一个线程结束。
代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
所有线程都有一个线程号,也就是Thread ID。其类型为pthread_t。通过调用pthread_self()函数可以获得自身的线程号。
 
参考资料:http://baike.baidu.com/link?url=lmnX74Y8XmpO899avy5qVTQmGyLCUffACb4J-1uFf93rhXnj8vM4xbe7htdIY3BwGDKVSwgZxGRKltlPa3O--a
     https://www.ibm.com/developerworks/cn/linux/thread/posix_thread1/

POSIX线程接口编程学习心得的更多相关文章

  1. Linux简单编程学习心得

    在Linux环境下简单编程学习心得 linux编程过程 在上周的<信息安全设计基础>的课程学习中学习到了在虚拟的linux环境下简单的编程.学习过程中接触到了vim.gcc和gcd在实验楼 ...

  2. windows API 核心编程学习心得

    一.错误处理 在内部,当windows函数检测到错误时,它会使用“线程本地存储区”的机制将相应的错误代码与“主调线程”关联到一起. winError.h 一般在C:\Program Files\Mic ...

  3. 在 POSIX 线程编程中避免内存泄漏

    检测和避免 POSIX 线程内存泄漏的技巧 POSIX 线程(pthread)编程定义了一套标准的 C 编程语言类型.函数和常量 — 且 pthreads 提供了一种强大的线程管理工具.要充分使用 p ...

  4. Linux 系统编程 学习:11-线程:线程同步

    Linux 系统编程 学习:11-线程:线程同步 背景 上一讲 我们介绍了线程的属性 有关设置.这一讲我们来看线程之间是如何同步的. 额外安装有关的man手册: sudo apt-get instal ...

  5. Posix线程编程指南

    Posix线程编程指南 Posix线程编程指南... 1 一线程创建与取消... 2 线程创建... 2 1.线程与进程... 2 2. 创建线程... 2 3. 线程创建属性... 2 4. 创建的 ...

  6. Posix线程编程指南(1)

    这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第一篇将向您讲述线程的创建与取消.   一.线程创建 1.1 线程与进程相对进程而言,线程是一 ...

  7. 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理

    1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...

  8. Posix线程编程指南(4) 线程终止

    线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式:非正常终止是 ...

  9. 阶段2-新手上路\项目-移动物体监控系统\Sprint2-摄像头子系统开发\第2节-V4L2图像编程接口深度学习

    参考资料: http://www.cnblogs.com/emouse/archive/2013/03/04/2943243.htmlhttp://blog.csdn.net/eastmoon5021 ...

随机推荐

  1. asymmetric cryptographic algorithm

    https://baike.baidu.com/item/非对称加密算法/1208652?fr=aladdin 主要算法 编辑 RSA.Elgamal.背包算法.Rabin.D-H.ECC(椭圆曲线加 ...

  2. kubernetes实战(四):k8s持久化安装rabbitmq集群

    1.下载文件 https://github.com/dotbalo/k8s/ 2.创建namespace kubectl create namespace public-service 如果不使用pu ...

  3. 如何编写一个python项目

    https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001397616003925a ...

  4. win安装mysql

    在这讲解的是有关于通过zip解压安装MySQL的方法.有看了网上的其它的教程,讲的有些不够完善,也自己写一篇简述一下.个人还是建议看官方的参考文档非常之详细:https://dev.mysql.com ...

  5. Shell特殊变量介绍与实践 $0

    2.$0特殊变量的作用及变量实践$0的作用为取出执行脚本的名称(包括路径) ,下面是该功能的实践.范例4-4:获取脚本的名称及路径. [root@salt-client- sh1]# cat n1.s ...

  6. Spark的RDD原理以及2.0特性的介绍

    转载自:http://www.tuicool.com/articles/7VNfyif 王联辉,曾在腾讯,Intel 等公司从事大数据相关的工作.2013 年 - 2016 年先后负责腾讯 Yarn ...

  7. 29张截图-全新安装CentOS7.5-超详细!

    目录 全新安装CentOS7.5 配置虚拟机 调整网卡名称 配置时区,分区,关闭安全工具 配置网络参数 配置root账户密码 参考链接 全新安装CentOS7.5 可以到这里下载镜像https://m ...

  8. InFusion错误类型分析

    1       God Class 1.1     特征 上帝类通常过多的操纵其他类的数据,从而破坏了类的封装性.上帝类从其他类中获得功能,同时增加了自身的耦合性,通常会导致自己具有规模过大和较高的复 ...

  9. iOS重签名脚本

    unzip xxx.ipa //解压ipa rm -rf Payload/ xxx.app/_CodeSignature //删除旧签名 cp newEmbedded.mobileprovision ...

  10. 抓包工具Charles简单使用介绍

    一是拦截别人软件的发送的请求和后端接口,练习开发. 二是自己后端返回的response拦截修改后再接收以达到测试临界数据的作用. 三写脚本重复拦截抓取别人的数据. 四支持流量控制,可以模拟慢速网络以及 ...