线程终止:

如果进程中的任意线程调用了exit、_Exit或者_exit,那么整个进程就会终止,与此类似,如果默认的动作是终止进程,那么发送到线程的信号就会终止整个进程

单个进程可以通过三种方式退出,因此可以在不终止整个进程的情况下,停止它的控制流

1.线程可以简单地从启动例程中返回,返回值是线程的退出码

2.线程可以被同一进程中的其他进程取消

3.线程调用pthread_exit

rval_ptr参数是一个无类型指针,与传给启动例程的单个参数类似,进程中其他线程也可以通过调用pthread_join函数访问这个指针。

当一个进程通过调用pthread_exit退出或者简单地从启动例程中返回时,进程中的其他线程可以通过调用pthread_join函数获得该线程的退出状态。

在默认情况下,线程的终止状态都会保存直到对该线程调用pthread_join。如果线程已经被分离,线程的底层存储资源可以在线程终止时被收回,在线程被分离后,不能用pthread_join函数等待它的终止状态,因为对分离状态的线程调用pthread_join会产生未定义行为,可以调用pthread_detach分离线程。

线程同步:

当多个控制线程共享相同的内存时,需要确保每个进程看到一致的数据视图,如果每个线程使用的变量都是其他线程不会读取和修改的,就不存在一致性的问题。同样,如果变量是只读的,多个线程读取该变量也不会有一致性的问题,但是当一个线程可以修改的变量,其他线程也可以读取或更改时,我们就需要对这些线程进行同步,确保它们在访问变量的存储内容时不会访问到无效的值。

当一个线程修改变量时,其他线程在读取这个变量时可能会看到一个不一致的值,在变量修改时间多于一个存储器访问周期的处理器结构中,当存储器读与存储器写这两个周期交叉时,这种不一致就会出现。

下图,线程A读取变量然后给这个变量赋予一个新的数值,但写操作需要两个存储器周期,当线程B在这两个存储器周期中间读取这个变量,会得到不一致的值。

为了解决这个我难题,不得不使用锁,同一时间只允许一个线程访问变量,如图:

如果线程B希望读取变量,首先要获取锁,当线程A更新变量时,也需要获取同样的锁,这样线程B在线程A释放锁之前就不能读取变量。

两个或多个线程试图在同一时间修改同一变量时,也需要进行同步。

如果数据总是以顺序一致出现的,就不需要额外的同步,当多个线程观察不到数据的不一致时,操作就是顺序一致的。

在顺序一致的环境中,可以把数据修改操作解释为运行线程的顺序操作步骤,线程A对变量增加1,B对变量增加1,两个线程的任何操作顺序都不可能让变量出现除了上述值以外的其他值。

互斥量:

可以使用pthread的互斥接口来保护数据,确保同一时间只有一个线程访问数据。从本质上说是一个锁,在访问共享资源前对互斥量进厂设置(加锁),在访问完成后释放互斥量。只有将所有线程都设计成遵守相同数据访问规则的,互斥机制才能工作。

互斥量是用pthread_mutex_t数据类型表示的,首先要进行初始化,可以把它设置为常量PTHREAD_MUTEX_INITIALIZER,也可通过调用pthread_mutex_init函数进行初始化,如果动态分配互斥量(比如通过调用malloc函数),在释放内存前需要调用pthread_mutex_destory。

要用默认的属性初始化互斥量,只需要把attr设置为NULL

对互斥量加锁,需要调用pthread_mutex_lock,如果互斥量已经上锁,调用线程将阻塞直到互斥量解锁,解锁要调用pthread_mutex_unlock。

如果线程不希望被阻塞,可以使用pthread_mutex_trylock尝试对互斥量进行加锁,如果发现未锁,那么就会加锁,并返回0.否则会失败。

避免死锁:如果线程试图对同一个互斥量加锁两次,那么自身就会陷入死锁状态,还有其他方式也能产生死锁。

可以通过仔细控制互斥量加锁的顺序来避免死锁的发生,比如所有线程总是在对互斥量b加锁前锁住互斥量A,那么使用两个互斥量就不会产生死锁。

函数pthread_mutex_timelock

当程序试图获取一个已加锁的互斥量时,pthread_mutex_timelock互斥量允许绑定进程阻塞时间,pthread_mutex_timelock与pthread_mutex_lock是基本等价的,但是达到超过时间值时,pthread_mutex_timelock不会对互斥量进行加锁,而是返回错误码ETIMEOUT。

读写锁:

读写锁和互斥量类似,不过读写锁允许更高的并行性,互斥量要么是锁住状态,要么是不加锁状态,而且一次只能一个线程可以对其加锁。读写锁有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但多个线程可以同时占有读模式的读写锁。也就是说,当读写锁是写加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞,当在读状态时,所有试图以读模式对它进行加锁的线程都可得到访问权,当读写锁处于读模式锁住状态时,有一个线程试图写模式获取锁时,读写锁通常会阻塞随后的读模式锁请求,这样可以避免读模式锁长期占用。

读写锁非常适合对数据结构读的次数远大于写的情况,与互斥量相比,读写锁在使用之前必须初始化,在释放它们底层的内存之前必须销毁。

要在读模式下锁定读写锁,需要调用pthread_rwlock_rdlock,要在写模式下锁定,要调用pthread_rwlock_wrlock,不管以何种方式锁住读写锁,都可以调用pthread_rwlock_unlock解锁。

条件变量:是线程可用的另一种同步机制,条件变量给多个线程提供一个汇合的场所,条件变量和互斥量一起使用,允许线程以无竞争的方式等待特定的条件发生。

条件本身是由互斥量保护的,线程在改变条件状态之前必须首先锁住互斥量,其他进程在获得互斥量之前不会察觉到这种改变,因此互斥量必须在锁定以后才能计算条件。

在使用条件变量之前,必须先要对它进行初始化,由pthread_cond_t数据类型表示的条件变量可以用两种方式进行初始化。

使用pthread_cond_wait等待条件变量变成真,如果在给定时间不能满足,生成一个返回错误码的变量。从pthread_cond_wait调用成功返回时,线程需要重新计算条件,因为另一个线程可能已经运行并改变了条件。

有两个函数可以用于通知线程条件已经满足,pthread_cond_signal函数至少能唤醒一个等待该条件的线程,pthread_cond_broadcase函数则能唤醒等待该条件的所有线程。

屏障:是用户协调多个线程并行共走的同步机制,屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后从该点继续执行。可以使用pthread_barrier_init函数对屏障初始化,pthread_barrier_destroy函数反初始化。

init函数中,count参数指定在允许所有线程继续运行之前,必须到达屏障的线程数目。attr参数指定屏障对象的属性,NULL表示默认属性。

用pthread_barrier_wait函数来表明,线程已完成工作,准备等所有其他线程赶上来,调用这个函数的线程在屏障计数未满足条件时,会进入休眠状态,如果该线程是最后一个调用这个函数的进程,就满足了屏障计数,所有的线程都会被唤醒。

一旦达到屏障计数值,而且线程处于非阻塞状态,屏障就可以被重用。

要注意的是,一般屏障计数值设置为工作线程数+1,因为还有主线程。

转载于:https://www.cnblogs.com/sichenzhao/p/9320360.html

unix环境高级编程-线程(2)相关推荐

  1. UNIX环境高级编程——线程

    线程包含了表示进程内执行环境必需的信息,其中包括进程中标示线程的线程ID.一组寄存器值.栈.调度优先级和策略.信号屏蔽字.errno变量以及线程私有数据. 进程的所有信息对该进程的所有线程都是共享的, ...

  2. UNIX环境高级编程——线程同步之条件变量以及属性

    条件变量变量也是出自POSIX线程标准,另一种线程同步机制.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量来 ...

  3. 【UNIX环境高级编程】线程同步

    当多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图.如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题.同样,如果变量是只读的也不会有一致性问题.但是,当一个线程可 ...

  4. 《UNIX环境高级编程(第3版)》——1.7 出错处理

    本节书摘来自异步社区<UNIX环境高级编程(第3版)>一书中的第1章,第1.7节,作者:[美]W. Richard Stevens , Stephen A.Rago著,更多章节内容可以访问 ...

  5. unix环境高级编程 pdf_UNIX系统编程宝典,每一本都值得程序员珍藏

    这几本UNIX系统编程宝典,重印无数次,几代程序员都视如珍宝的几本书,小编在出版圈里快十年了,见证了这本书图灵版.异步社区版的出版.营销,对这套书倾注了一定的感情.今天继续分享给你们,好书总会有人还不 ...

  6. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  7. UNIX环境高级编程笔记

    1.setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, len);   SO_REUSEADDR套接口选项允许为以下四个不同的目的提供服务:   ...

  8. 《Unix环境高级编程》学习笔记:从点到面

    以前在课堂上学习过<Unix初级教程(第四版)>,对于Unix有了一点了解.由于以后使用的需要,要对它进行比较深入的学习,为此需要阅读不少的书籍,这本<Unix环境高级编程>便 ...

  9. 《UNIX环境高级编程(第3版)》——2.6 选项

    本节书摘来自异步社区<UNIX环境高级编程(第3版)>一书中的第2章,第2.6节,作者:[美]W. Richard Stevens , Stephen A.Rago著,更多章节内容可以访问 ...

最新文章

  1. jieba分词流程及部分源码解读(一)
  2. 查看PID 进程是否存在的一个小技巧
  3. 三种python序列类型
  4. 报告一下近期读书情况
  5. 信号量优先级反转(翻转)与优先级继承
  6. __attribute__((unused)):可能不会用到,消除编译警告
  7. shrio 权限管理filterChainDefinitions过滤器配置(转)
  8. 基于OpenGL编写一个简易的2D渲染框架-11 重构渲染器-Renderer
  9. matlab作图函数的总结与分析.pdf,Matlab作图函数的总结与分析_黄琼湘
  10. 【Vue项目实践】实现在线预览word文件、excel文件
  11. 参考文献在论文中进行引用标注
  12. 2019.08.17 日常总结
  13. 基于javaweb+JSP+Servlet宿舍管理系统(超级管理员、宿舍管理员、学生)
  14. 关于面试技巧和简历写法的一些总结
  15. 在OpenWRT路由器上自动更新github等网站的hosts
  16. Simulink建模:Simulink PWM死区时间插入仿真
  17. TCP/IP协议十二:关于MAC地址和IP地址在传输过程中变与不变的问题
  18. 宇视各类产品默认地址列表
  19. 英语学习——新婚贺词
  20. 安卓沉浸式状态栏_安卓平板也能有品质感,小新Pad Pro上手

热门文章

  1. Hyperledger Fabric 1.0 从零开始(五)——运行测试e2e
  2. mssql,mysql,oracle中查询数据库表的比较
  3. nyoj116 士兵杀敌(二)树状数组 插点问线
  4. 前台特效(6) 折叠栏目(动画效果)
  5. 去上海参加MySQL 用户大会的感受
  6. android开发 修改标题栏背景_基于.NET的APP开发方式中MobileForm的使用smobiler
  7. 求最大元最小元极大元极小元_极大元、最大元.ppt
  8. 酶促反应动力学_酶促反应动力学实验
  9. 设计模式 — 创建型模式 — 建造者模式
  10. 5G NGC — 系统架构