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:标准 ...
随机推荐
- BCD码转换为十进制或者十进制转为BCD码
BCD码其实就是之前在数字电路中说的 用4位二进制数值 来表示一个0-9中的数字,例如: 0000=0 0001=1 0010=2 0011=3也就是说如果把一个数字作为一个BCD码,例如: 11 2 ...
- VueX-状态管理器
一.VueX功能与解决的问题 1.中央状态管理器的功能: 1.1.可以管理共享状态1.2.提供一 个可修改状态的方法1.3.提供状态获取的方法1.4.状态更改后,有通知机制 2.中央状态管理器解决的问 ...
- 常见gcc编译问题解决方法集
除非明确说明,本文内容仅针对x86/x86_64的Linux开发环境,有朋友说baidu不到,开个贴记录一下(加粗字体是关键词):用"-Wl,-Bstatic"指定链接静态库,使用 ...
- Thread.sleep() 和 Thread.yield() 区别
1. Thread.yield(): api中解释: 暂停当前正在执行的线程对象,并执行其他线程. 注意:这里的其他也包含当前线程,所以会出现以下结果. public class Test exten ...
- (一)JQuery动态加载js的三种方法
Jquery动态加载js的三种方法如下: 第一种: $.getscript("test.js"); 例如: <script type="text/javascrip ...
- underscore概况
看的是1.3.3,这个版本的中文源码解释比较多. 函数的中文注释:http://www.css88.com/doc/underscore1.5.2/#difference 源码的中文注释:http:/ ...
- GPU的历史:从固定管线到可编程管线再到通用计算平台
开始的时候GPU不能编程,也叫固定管线的,就是把数据按照固定的通路走完. 和CPU同样作为计算处理器,顺理成章就出来了可编程的GPU,但是那时候想在GPU上编程可不是容易的事,你只能使用GPU汇编来写 ...
- sitecore 缓存管理器
namespace XXX.Shared.Infrastructure.Caching { using System; using System.Collections.Generic; using ...
- docker把系统盘占满后的恢复
docker报[Error response from daemon: Error running DeviceCreate (createSnapDevice) dm_task_run failed ...
- 原创:MVC 5 实例教程(MvcMovieStore 新概念版:mvc5.0,EF6.01) - 1、初露锋芒
说明:MvcMovieStore项目已经发布上线,想了解最新版本功能请登录 MVC 影视(MvcMovie.cn) 进行查阅.如需转载,请注明出处:http://www.cnblogs.com/Dod ...