多线程编程

一、线程的基本概念
        与进程相比,多线程是一种非常“节俭”的多任务操作方式。在linux操作系统下,启动一个新进程必须给
    它分配独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种“昂贵”的多任务
    工作方式;而运行一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个
    线程所花费的空间远远小于启动一个进程所花费的空间,线程间彼此切换所需的时间也远远少于进程间切换
    所需要的时间。
        进程作为独立的实体,它为线程提供运行的资源并构成静态环境。线程是处理机调度的基本单位。如果
    说进程概念很好的描述了单机操作系统行为,那么线程概念则很好的描述了多机系统的并行处理行为。    
        多线程工作方式提供了线程间方便的通信机制。由于同一进程下的线程之间共享数据空间,所以一个线
    程的数据可以直接为其它线程使用,这不仅快捷,而且方便。
        多线程程序还有以下优点:提高应用程序响应,使CPU系统更加有效,改善程序结构。
        
二、线程的实现
        linux系统下的多线程遵循POSIX线程接口,称为PTHREAD。编写linux下的多线程程序,需要使用头文件
    pthread.h,连接时需要使用库文件libpthread.a.(因此编译时需要添加选项:-lpthread)
    
    (1)创建线程:即确定调用该线程函数的入口点,通常使用的函数是pthread_create。
    
     函数原型:

        int pthread(pthread_t * thread, pthread_attr_t * attr, void * ( * start_routine) (void *), void arg));pthread: 线程标识符attr: 线程属性start_routine:线程运行函数的起始地址(线程函数名)arg:运行函数的参数(线程函数所需的参数)返回值:创建成功——返回0,若不为0则为创建线程失败(EAGAIN,EINVAL)

(2)线程挂起
            一个进程中的多个线程是共享数据段的,因此通常在线程退出后,退出线程所占用的资源并不会随
        着线程的终止而释放。就如进程中的wait(),线程之间使用pthread_join()函数将当前线程挂起,等待
        线程的结束。pthread_join()是一个线程阻塞的函数,调用它的函数将一直等待到被等待线程的结束。
            需要注意的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余的将
        返回错误代码。
        
        函数原型:

            int pthread_join(pthread_t th, void ** thread_return);th: 被等待的线程标识符thread_return:用户定义的指针,用于存储被等待线程的返回值

(3)线程的结束:1、相关线程函数运行结束;2、调用pthread_exit()函数
    
        函数原型:

            void pthread_exit(void * retval)retval:函数的返回代码,即thread_return

示例:

            void thread(void){}//线程运行函数pthread_t id;pthread(&id,NULL,(void *)thread,NULL);//创建线程,第一个NULL —— 生成默认属性的线程,第二个NULL —— 线程运行函数不需要参数pthread_join(id,NULL);//挂起线程

三、修改线程属性
        线程属性值不能直接设置,需要调用相关的函数进行操作,初始化的函数为pthread_attr_init,这个函
    数必须在pthread_create函数之前调用。属性对象包括是否绑定、是否分离、堆栈地址、堆栈大小和优先级。
    默认的属性为非绑定、非分离、缺省1MB的堆栈和与父进程同样级别的优先级。对于大多数程序来说,使用默
    认属性就够了。
    
    1、绑定
        关于绑定涉及到另一个概念:轻进程LWP(Light Weight Process)。可理解为内核线程,系统对线程
    资源的分配和对线程的控制是通过轻进程来实现的。默认情况下,由系统来控制启动多少轻进程、哪些轻进
    程控制哪些线程,这种状态称为非绑定的。绑定即某个线程固定的“绑”在一个轻线程上。被绑定的线程具
    有较高的反应速度(CPU时间片的调度是面向轻进程的)。
        通过设置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足实时反应之类的要求
        
    创建一个绑定的线程:(pthread_attr_setscope)

        pthread_attr_t attr;pthread_t tid;pthread_attr_init(&attr);//初始化属性值,均设为默认值pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);//设置绑定状态pthread_create(&id, &attr, (void *) my_function, NULL);attr: 指向属性结构的指针绑定类型:PTHREAD_SCOPE_SYSTEM(绑定的),PTHREAD_SCOPE_PROCESS(非绑定的)

2、分离
        线程的分离状态决定一个线程以什么样的方式来终止自己。
            非分离:原有的线程等待创建的线程结束,只有pthread_join()函数返回时才释放所占资源。
            分离:不被其他进程所等待,运行结束后马上释放所占资源。
            
        线程分离状态的函数:

            pthread_attr_setdetachstate(pthread_attr_t * attr, int detachstate)detachstate: PTHREAD_CREATE_DETACHED(分离线程), PTHREAD_CREATE_JOINABLE(非分离线程)

如果设置了一个线程为分离线程,而这个线程运行又非常快,它很可能在pthread_create函数
            返回之前就终止了,这样调用pthread_create的线程就可能得到错误的线程号。为避免这种情况,
            通常在创建的线程里调用pthread_cond_timewait函数,让这个线程等待会儿。
            
    3、优先级
        优先级存放在结构sched_param中,用函数pthread_attr_getschedparam和pthread_attr_setschedparam
    进行存放。一般而言是先取优先级,然后对优先级进行修改后再存放回去。
    
    例如:

        pthread_attr_t attr;//属性pthread_t tid;//线程标识符sched_param param;//优先级int newprio = 20;//新的优先级pthread_attr_init(&attr);pthread_attr_getschedparam(&attr,&param);/取出优先级param.sched_priority = newprio;//修改优先级pthread_attr_setschedparam(&attr,&param);//写回优先级pthread_create(&tid, &attr, (void *)myfunction, NULL);

四、多线程访问控制
        由于多线程共享进程的资源和地址空间,因此对这些资源进行操作时,必须考虑到线程间资源访问的唯
    一性问题。
        互斥锁有一个明显的缺点:只有两种状态(锁定和非锁定),而条件变量通过允许线程阻塞和等待另一个线
    程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。

1、pthread_cond_init ()函数 —— 用于初始化一个条件变量
        int pthread_cond_init(pthread_cond_t * cond, __const pthread_condattr_t * cond_attr)
        
        cond: 指向结构pthread_cond_t的指针
        cond_attr: 条件变量的属性结构(默认值——PTHREAD_PROCESS_PRIVATE)
        
        初始化条件变量只有未被使用时才能重新初始化或被释放。
        释放条件变量的函数:pthread_cond_destroy(pthread_cond_t cond)
        
    2、pthread_cond_wait()函数 —— 使线程阻塞在一个条件变量上
        extern int pthread_cond_wait(pthread_cond_t * __restrict__cond,
                                            pthread_mutex_t * __restrict__mutex)
                                            
        线程解开mutex指向的锁并被条件变量cond阻塞。
        
    3、pthread_cond_timedwait()函数 —— 用于阻塞线程的另一个函数
        extern int pthread_cond_timedwait __P((pthread_cond_t * __restrict__cond,
                    pthread_mutex_t * __restrict__mutex, __const struct timespec * __abstime))
            
        它比thread_cond_wait()函数多了一个时间参数,经历abstime时间后,即使条件变量不满足,
        阻塞也被解除。
        
    4、pthread_cond_signal()函数 —— 用来释放被阻塞在条件变量cond上的一个线程。
        extern int pthread_cond_signal(pthread_cond_t * __cond)

需要注意的是,必须用保护条件变量的互斥锁来保护这个函数,否则条件满足信号又可能在测试条件和
        调用pthread_cond_wait()函数之间被发出,从而造成无限制的等待。
        
    5、其它常用线程函数
        获得父进程ID:
            pthread pthread_self(void)
        测试两个线程号是否相同:
            int pthread_equal(pthread_t __thread, pthread_t __thread2)
        互斥量初始化:
            int pthread_mutex_init(pthread_mutex_t * , __const pthread_mutexattr_t * )
        销毁互斥量:
            int pthread_mutex_destroy(pthread_mutex_t *__mutex)
        再试一次获得对互斥锁量的锁定(非阻塞)
            int pthread_mutex_trylock(pthread_mutex_t *__mutex)
        锁定互斥量(阻塞)
            int pthread_mutex_lock(pthread_mutex_t *__mutex)
        解锁互斥量
            int pthead_mutex_unlock(pthread_mutex_t *__mutex)
        条件变量初始化
            int pthread_cond_init(pthread_cond_t *__restrict__cond,
                                    __const pthread_condattr_t *__restrict__cond_attr)
        销毁条件变量cond
            int pthread_cond_destroy(pthread_cond_t *__cond)
        唤醒线程等待条件变量
            int pthread_cond_signal(pthread_cond_t *__cond)
        等待条件变量
            int pthread_cond_wait(pthread_cond_t *__restrict__cond,
                                        pthread_mutex_t * __restrict__mutex)
        在指定的时间到达前等待条件变量
            int pthread_cond_timewait(pthread_cond_t *__restrict__cond,
                phread_mutex_t *__restrict__mutex, __const struct timespec *__restrict __abstime)

转载于:https://blog.51cto.com/tobeys/1720019

【linux】多线程编程(c语言编程)相关推荐

  1. linux c语言 ppt,linux操作系统下c语言编程入门.ppt

    linux操作系统下c语言编程入门.ppt Linux操作系统下C语言编程入门 CNT Linux操作系统简介基础知识进程介绍文件操作时间概念消息管理线程操作网络编程Linux下C开发工具介绍 一 L ...

  2. linux操作系统下 c语言编程入门

    linux操作系统下 c语言编程入门 (一)目录介绍 1)Linux程序设计入门--基础知识 2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门 ...

  3. [转] linux操作系统下c语言编程入门

    (一)目录介绍 1)Linux程序设计入门--基础知识  2)Linux程序设计入门--进程介绍  3)Linux程序设计入门--文件操作  4)Linux程序设计入门--时间概念  5)Linux程 ...

  4. linux操作系统下c语言编程入门

    linux操作系统下c语言编程入门  整理编写:007xiong  原文:Hoyt等 (一)目录介绍 1)Linux程序设计入门--基础知识  2)Linux程序设计入门--进程介绍  3)Linux ...

  5. 【转贴】linux操作系统下c语言编程入门

    [转贴]linux操作系统下c语言编程入门 发信人: Lerry (驴是的念来过倒·杏红等头墙上爬), 信区: Linux 标 题: linux操作系统下c语言编程入门 发信站: 哈工大紫丁香 (Fr ...

  6. Linux下C语言串口应用编程,Linux下串口C语言编程

    Linux下串口C语言编程 (5页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 串口操作代码#include #include #inclu ...

  7. 实验linux下的编程,实验四 Linux下的C语言编程;

    <实验四 Linux下的C语言编程;>由会员分享,可在线阅读,更多相关<实验四 Linux下的C语言编程;(5页珍藏版)>请在人人文库网上搜索. 1.实验四Linux 下的 C ...

  8. 南工程c语言实验报告,Linux环境下-C语言编程实验报告(1)(总4页).doc

    Linux环境下-C语言编程实验报告(1)(总4页).doc 西 安 邮 电 大 学 (计算机学院)课内实验报告实验名称 Linux环境下 C语言编程 专业名称 网络工程班 级 1203班 学生姓名 ...

  9. linux环境c语言课程设计,linux环境下c语言编程课程设计

    linux环境下c语言编程课程设计 (14页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 1/14LINUX操作系统教程课程设计题目算术 ...

  10. linux下的c语言编程实验4,实验四-Linux下的C语言编程

    实验四Linux 下的 C 语言编程 四.实验内容 本实验要求在LINUX/UNIX环境下用C语言编写三个具体的SHELL命令,基本涉及了LINUX/UNIX文件系统中较为常用的有关文件操作的系统调用 ...

最新文章

  1. 微信小程序让屏幕自动向下滚动
  2. 一个“Internal”牵扯出的代码泄露,阿里云独家回应
  3. 联合使用 HTML 5、地理定位 API
  4. 设置XMLHttpRequest“ withCredentials”属性问题,axios请求不成功
  5. python网络爬虫系列教程——Scrapy框架应用全解
  6. 我爱淘冲刺阶段站立会议2每天任务2
  7. 编写python程序、计算账户余额_《易学Python》——第1章 为何学习Python 1.1 学习编程...
  8. pta——点赞,打印杨辉三角,吃火锅(c语言)
  9. socket编程 error: storage size of ‘sockAddr’ isn’t known
  10. [QDialog]qt虚拟键盘的实现以及qdateedit实现打开虚拟键盘
  11. dede后台更改mysql数据库密码
  12. 2021长安二中高考成绩查询,陕西33所高中2020年高考数据已公布!速看
  13. ubuntu 命令行 上的一些常见的快捷键和命令;无法输入字符等
  14. asp.net ajax1.0基础回顾(三):UpdatePanel的基本用法
  15. 笔试总结——0322联通软笔C++
  16. 计算机网络实验一:网络常用命令
  17. CAD编辑器图片转换为CAD的方法
  18. Java初学记 Java 通过键盘一次输入多个数据,获取长宽高,求长方体的面积和体积。
  19. 成功人生十大要素!(这就是人与人的差距啊~)
  20. mysql exercise --- one 建库建表练习参考

热门文章

  1. 推荐13个CSS3快速开发工具
  2. vijos p1063(迎春舞会之集体舞)
  3. 云计算五种定义辨析[摘]
  4. hdu4923 f(A,B)分段处理
  5. 【错误记录】Google Play 上架报错 ( 您上传的 APK 没有经过 Zipalign 处理,请对 APK 运行 Zipalign 工具,然后重新上传。)
  6. 【Android 组件化】路由组件 ( 构造路由表中的路由信息 )
  7. spotlight监控linux性能
  8. 在 mac OS 中安装 xgboost python 包
  9. Gym 101606 F-Flipping Coins(概率dp)
  10. canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)...