Linux系统编程:线程控制
一、提出问题
问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系统编程:线程控制的更多相关文章
- Linux系统编程——线程私有数据
在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...
- linux系统编程--线程
安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...
- Linux系统编程 —线程同步概念
同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...
- linux系统编程--线程同步
同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...
- Linux系统编程 —线程属性
在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性.一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题. 但是, ...
- Linux 系统编程 学习:11-线程:线程同步
Linux 系统编程 学习:11-线程:线程同步 背景 上一讲 我们介绍了线程的属性 有关设置.这一讲我们来看线程之间是如何同步的. 额外安装有关的man手册: sudo apt-get instal ...
- Linux 系统编程 学习:09-线程:线程的创建、回收与取消
Linux 系统编程 学习:09-线程:线程的创建.回收与取消 背景 我们在此之前完成了 有关进程的学习.从这一讲开始我们学习线程. 完全的开发可以参考:<多线程编程指南> 在Linux ...
- Linux 系统编程 学习:10-线程:线程的属性
Linux 系统编程 学习:10-线程:线程的属性 背景 上一讲我们介绍了线程的创建,回收与销毁:简单地提到了线程属性.这一讲我们就来具体看看,线程的属性. 概述 #include <pthre ...
- 读书笔记之Linux系统编程与深入理解Linux内核
前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...
- Linux系统编程【转】
转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准 ...
随机推荐
- kali下搭建WiFi钓鱼热点
在linux下建立无线热点并不像在windows下开启网络共享或者使用无线网卡驱动设置AP模式即可. linux下的无线共享要用到两个软件:hostapd(创建无线热点).dnsmasq(dns服务和 ...
- PG数据库错误: 检测到OA幸运飞艇源码ShareLock死锁处理
PostgreSQL 是一个免费数据库,OA幸运飞艇源码下载,详情咨询[企娥166848365]对于处理分析型+交易型混合型系统来说确实很不错,特别是版本的升级到11.2后性能提升很多,很多运行机制跟 ...
- 基于Extjs的web表单设计器 第一节
前面一节介绍了表单设计器的背景和最终的大概样式,本节主要介绍表单设计器的需求及功能设计. 在讲需求之前先明确几个常用的概念: 主表或者卡片表——具有多行多列的一个区域的控件块,如下图所示. 明细表—— ...
- CentOS6.3安装MySQL5.5
1.查看系统是否安装了MySQL 使用命令: #rpm -qa | grep mysql 2.卸载已安装的MySQL 卸载mysql命令如下: #rpm -e --nodeps mysql-libs ...
- django def validate_column和validate
VIewDemo class RegUserSet(mixins.CreateModelMixin,viewsets.GenericViewSet): serializer_class = RegUs ...
- 创建可复用的自定义 ASP.NET MVC Helpers
通常,在ASP.NET MVC项目中App_Code目录下新建.cshtml编写类似下方的代码就能创建自定义的MVC Helper了, 假设文件名为StrHelper.cshtml,那么在别的视图中的 ...
- unity 移动物体的方式
1. 简介 在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position. 2. 通过Transform组件移动物体 Transform 组件用于描述物体在 ...
- NIO-直接内存
写NIO程序经常使用ByteBuffer来读取或者写入数据,那么使用ByteBuffer.allocate(capability)还是使用ByteBuffer.allocteDirect(capabi ...
- web思维导图(前期)
- 从【BZOJ4173】谈做题技巧
题目描述 ----------------------------------------------------------------------------------------------- ...