一、提出问题

问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. windows平台下spark-shell配置

    一.下载安装spark,http://spark.apache.org/,选择合适版本后下载到本地,解压,bin目录下spark-shell文件就是spark命令行交互的入口. 二.下载安装windo ...

  2. Android-开关机的广播

    在上一篇博客Android-sdcard广播的接收处理,中介绍了,如何订阅接收者,去接收系统发送的Sdcard状态改变广播,而这篇博客是订阅接收者,去接收开机/关机的广播 Android操作系统在开机 ...

  3. asp.net 使用Oracle数据库

    asp.net下使用oracle会发生“未能加载文件或程序集‘Oracle.DataAccess’或它的某一个依赖项”的错误.这说明Oracle的驱动没有安装好,或者版本不对的错误. 1.检查Orac ...

  4. solrconfig.xml配置详解

    solrconfig.xml配置文件主要定义了SOLR的一些处理规则,包括索引数据的存放位置,更新,删除,查询的一些规则配置. 可以在tomcat的安装路径下找到这个文件C:\Program File ...

  5. 在相应目录下新建或读取xml文件

    string path = AppDomain.CurrentDomain.BaseDirectory+"UserContent1.xml"; //判断相应路径下文件是否存在 不存 ...

  6. django drf 自定义jwt用户验证逻辑

    新建Backend类 from django.contrib.auth.backends import ModelBackend from django.shortcuts import render ...

  7. sqlserver排名函数

    在做开发的时候,排名函数是sqlserver经常用到的函数,在分页的时候需要用,分组的时候也要用,主要排名函数有row-number,rank(),dense-rank(),NTILE()接下来详细说 ...

  8. C博客第01次作业---顺序,分支结构

    1.本章学习总结 1.1 思维导图 1.2本章学习体会及代码量学习体会 1.2.1学习体会 经过了这一周的学习,从一开始对C语言一无所知,到现在能够写出基本的代码,感到非常开心. 学习C语言也并非想象 ...

  9. java学习笔记—c3p0连接池与元数据分析(42)

    第一步:导入c3p0包 第二步:在classpath目录下,创建一个c3p0-config.xml <?xml version="1.0" encoding="UT ...

  10. java public class和class的区别