一、提出问题

问1.线程存在的意义是什么?什么时候适合使用多线程?

答1.在单进程环境中实现多任务,线程可访问其所在进程的资源,例如内存、描述符等。对于单进程,如果要完成多项任务,这些任务只能依次执行,使用多线程可以让多个任务并行执行。

问2.线程的同步和异步有什么不同?同步实现机制分别有哪些?

答2.同步,顾名思义:相同的步调,就比如我们两条腿走路,左右脚之间互相协调,有节奏进行前进。在线程这里同步的意思就是,几个线程为了完成某个任务配合地、互相制约地执行。异步的概念同样可以理解,线程之间的执行没有依赖关系。同步机制适合在。同步的实现机制:互斥量、信号量、读写锁、条件变量。

二、常用函数

①创建线程

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

参数分析:

tidp:指向保存线程ID的变量
pthread_attr_t:设置线程属性,通常为NULL
start_rtn:该线程要运行的函数的起始地址。
arg:运行函数的参数。
返回值:成功--0,失败--出错编号

②退出线程:线程主动调用,属于正常退出的一种。

#include <pthread.h>
void pthread_exit(void *retval);

retval:指向即将退出的线程所执行的函数的返回值。这里不解的是为什么线程执行的程序的返回值要通过指针参数来返回?先放一下这个问题,或许后面会有答案。

③线程等待:让父进程等待指定的线程,直到该线程结束返回。

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

参数分析:

thread:要等待的线程ID
retval:指向要等待退出的线程的返回值,这里值得注意的是它是指针的指针。联系上边的内容,pthread_create()函数中指定的线程执行函数start_rtn()是个指针函数——返回值为指针,也就是说在函数执行到最后需要来一句类似于“return 指针”这样的语句,线程调用pthread_exit就意味着“结束返回”,也需要返回这么一个指针,这个指针就是通过pthread_exit函数的参数来设置,如此上边留下的问题就有答案了。同时,问题也来了:start_rtn()指针函数返回的指针值由谁来接受?线程结束时进程在做什么,可能执行其他线程,可能进程在等待某个线程的凯旋归来等等,嗯,如果线程刚好在等待这个线程,那么自然他可以获得线程结束时的返回值——指针,我们知道存放指针的变量叫指针的指针,所以就有了参数“void **retval”。
返回值:成功--0, 失败--错误号.

④获取线程ID:在线程中调用,获取自身线程的ID.

#include <pthread.h>
pthread_t pthread_self(void);

⑤线程资源释放:根据需要这是线程在退出之前要进行的操作。

#include <pthread.h>
void pthread_cleanup_push(void (*routine)(void*), void *arg);

参数:routine——清除函数,arg——传给清除函数的参数。

#include <pthread.h>
void pthread_cleanup_pop(int execute);

参数:execute——0:不执行push设置的清除函数;其他值执行。

问:这两个函数如何使用?有什么作用?

答:从调用pthread_cleanup_push()开始,到调用pthread_cleanup_pop()之前,期间如果线程中有调用pthread_exit()函数、或有异常退出,都将调用清除函数。特别注意:期间如果线程是执行return语句退出的绝不执行清除函数。pthread_cleanup_pop()函数参数只要非0就可“强行”执行清除函数。在设计程序时一个push对应一个pop,遵循先进后出原则。此外,在编写程序的时候如果push和pop不成对存在,编译怎么都是通不过的。作用:防止线程异常退出造成内存泄漏。

三、例程编写测试

 #include <stdio.h>
#include <pthread.h>
#include <unistd.h> /*线程清理函数*/
void *mythread_clean(void *arg)
{
printf("%s\n",(char *)arg);
return (void *);
} /*线程执行函数*/
void *mythread(void *arg)
{
printf("running in mythread.\n"); //将线程清理函数压入清除栈两次
pthread_cleanup_push( (void*)mythread_clean,"running in mythread clean handler." );
printf("mythread push complete.\n");
//如果参数为空--主动退出线程
if(!arg)
pthread_exit((void *));
pthread_cleanup_pop(); // 打印线程接收到的字符串参数
printf("*arg:%s\n",(char *)arg);
printf("sleep......\n");
sleep();
printf("exit......\n");
pthread_exit((void *));
} int main(int argc,char *argv[])
{
int err;
pthread_t tid;
void *tret; if(argc != )
{
printf("arg error.\n");
printf("ture usage:./app xxx\n");
}
//创建线程并执行线程执行函数
err=pthread_create(&tid,NULL,mythread,argv[]);
if(err!=)
{
printf("thread create error.\n");
return -;
} //阻塞等待线程退出,并获取线程的返回值
err=pthread_join(tid,&tret);
if(err!=)
{
printf("error .... \n");
return -;
}
printf("mythread return value %d.\n",(int)tret); return ;
}

thread.c

编译要点:pthread并非Linux系统的默认库,而是POSIX线程库。在编译的时候加上“-lpthread”选项。

测试结果:

编译时的那个警告是因为程序中把一个char型指针强制转换成int型变量值。

Linux系统编程:线程控制的更多相关文章

  1. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  2. linux系统编程--线程

    安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...

  3. Linux系统编程 —线程同步概念

    同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...

  4. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  5. Linux系统编程 —线程属性

    在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性.一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题. 但是, ...

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

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

  7. Linux 系统编程 学习:09-线程:线程的创建、回收与取消

    Linux 系统编程 学习:09-线程:线程的创建.回收与取消 背景 我们在此之前完成了 有关进程的学习.从这一讲开始我们学习线程. 完全的开发可以参考:<多线程编程指南> 在Linux ...

  8. Linux 系统编程 学习:10-线程:线程的属性

    Linux 系统编程 学习:10-线程:线程的属性 背景 上一讲我们介绍了线程的创建,回收与销毁:简单地提到了线程属性.这一讲我们就来具体看看,线程的属性. 概述 #include <pthre ...

  9. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

  10. Linux系统编程【转】

    转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准 ...

随机推荐

  1. linux平台 spark standalone集群 使用 start-all,stop-all 管理集群的启动和退出

    一.配置/etc/profile: 文件尾部增加以下内容: export SPARK_HOME=/home/spark/spark-2.2.0-bin-hadoop2.7 export PATH=$P ...

  2. 解决 sublime text 3 右键菜单栏出现多余的菜单项分隔符的问题

    很早之前装了一个插件 JavaScript Completions,虽然还没有用过它的高级功能,但随着 sublime text 3 逐渐成为我主要的编程工具,最近发现在右键点击文件出现的菜单栏中,菜 ...

  3. DW2.0

    一.DW2.0从企业的角度,吸引企业的原因: 1.数据仓库基础设施的成本不再持续增长.在第一代数据仓库中,技术基础设施的成本是不断增长的,随着数据量的增长,基础设施的成本会以指数级增长.但是使用DW2 ...

  4. GPS模块输出的NMEA数据ddmm.mmmm转换成dd.ddddd并在google Earth Pro中描点

      GPS模块输出的数据是NMEA格式,其中GPGGA字段包含我们需要的经纬度信息. 例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,12 ...

  5. s21day25 python笔记

    s21day25 python笔记 正则表达式 1.定义 定义:正则表达式是一种规则匹配字符串的规则 re模块本身只是用来操作正则表达式的,和正则本身没关系 为什么要有正则表达式? 匹配字符串 一个人 ...

  6. shell相关文件

    站在用户登录的角度来说,SHELL的类型: 登录式shell: 正常通常某终端登录 su - USERNAME  su -l USERNAME 非登录式shell: su USERNAME 图形终端下 ...

  7. JQuery中checkbox选择器

    今天我们讲的是如何选择HTML网页中CheckBox选择器 如下图,是几个checkbox <input type='checkbox'checked="checked"/& ...

  8. 官宣,PyTorch 1.0 稳定版本现已推出

    简评:快来一起快乐地学习吧. 随着 PyTorch 生态系统和社区继续为开发人员提供有趣的新项目和教育资源,今天(12 月 7日)在 NeurIPS 会议上发布了 PyTorch 1.0 稳定版.研究 ...

  9. 在eclipse中,用maven创建web项目

    备注:该文档是之前学习时,根据网上其他童鞋的经验自己测试后梳理,如有侵权,请勿怪,感谢! 1.在eclipse中用maven创建项目,右键new>>Maven Project 2.点击ne ...

  10. docker微服务部署之:四、安装docker、docker中安装mysql和jdk1.8、手动构建镜像、部署项目

    docker微服务部署之:三,搭建Zuul微服务项目 1.Centos7安装Docker 详见:Centos7安装Docker 2.Docker中安装jdk1.8 详见:使用Docker构建jdk1. ...