《APUE》读书笔记第十一章-线程
本章主要介绍了线程,了解如何使用多线程在单进程环境中来执行多任务。由于多个线程共享其进程空间,所以必须采用同步的机制来保护数据的一致性。
一.线程的概念
典型的Unix系统都可以看成只有一个控制线程,一个进程在同一时刻只能做一件事。但有了多线程,我们可以设计成在同一时刻进程能做不止一件事,每个线程处理各自独立的任务。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。
二.线程标识
- #include <pthread.h>
- int pthread_equal(pthread_t tid1,pthread_t tid2);//若相等则返回非0值,否则返回0
- pthread_t pthread_self(void);//返回调用线程的线程ID
三、线程创建、终止与清理
- int pthread_create(pthread_t *tid,const pthread_attr_t* attr,
- void* (*start)(void*),void* arg);
- //返回值:若成功则返回0,否则返回错误编号
单个线程可以通过下列三种方式退出,在不终止整个进程的情况下停止它的控制流.
- 线程只是从启动例程中返回,返回值是线程的退出码。
- 线程可以被同一进程中的其他线程取消。
- 线程调用pthread_exit。
但是这两个函数有一个限制,由于它们可以实现为宏,所以必须在线程相同的作用域中以匹配对的形式使用,pthread_cleanup_push的宏定义可包含字符{,在这种情况下对应的匹配字符}就要在pthread_cleanup_pop定义中出现。
- int pthread_join(pthread_t tid,void ** ptr);
- //若成功则返回0,否则返回错误编号
调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或被取消。ptr将包含返回码。
如果线程采用pthread_self函数使其处于分离状态,pthread_join调用就会失败.返回EINVAL.
- void pthread_cancel(pthread_t tid);//成功返回0,否则返回错误编号
线程可以安排它退出时的需要调用的函数,这与进程可以用atexit函数安排进程退出时需要调用的函数类似。线程可以建立多个清理处理程序,处理程序在栈中,也就是说他们的顺序与它们注册的顺序相反。
- void pthread_cleanup_push(void (*rtn)(void*),void *arg);
- void pthread_cleanup_pop(int execute);
当线程执行以下动作时调用清理函数,调用参数为arg.
- 调用pthread_exit时
- 响应取消请求时
- 用非零execute参数调用pthread_cleanup_pop时
如果execute参数置为0,清理函数将不被调用。
四.线程同步
当多个线程共享相同内存时,为了保持数据共享的一致性,我们采取线程同步的机制。线程同步有四种方法:
1.互斥量
可以通过使用pthread的互斥接口保护数据,确保同一时间只有一个线程访问数据.互斥量(mutex)从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。
- #include <pthread.h>
- int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);
- int pthread_mutex_destroy(pthread_mutex_t *mutex);
- int pthread_mutex_lock(pthread_mutex_t *mutex);
- int pthread_mutex_trylock(pthread_mutex_t *mutex);
- int pthread_mutex_unlock(pthread_mutex_t *mutex);
如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住的状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0.否则pthread_mutex_trylock就会失败,不能锁住互斥量,而返回EBUSY.
2.读写锁
读写锁与互斥锁类似,不过读写锁允许更高的并行性.读写锁有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。
当读写锁时写加锁状态时,在这个锁被解锁前,所有试图对这个锁加锁的线程都会被阻塞。当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是如果线程希望以写模式对此锁进行加锁,它必须阻塞到所有的线程释放读锁。
读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。
- #include <pthread.h>
- int pthread_rwlock_init(pthread_rwlock_t *rwlock,const pthread_rwlockaddr_t* attr);
- int pthread_rwlock_destroy(pthread_rwlock_t* rwlock);
- //成功时返回0,否则返回错误编号
- int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
3.条件变量
条件变量给多个线程提供了一个会合的场所,条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。
条件本身是由互斥量保护的。线程在改变条件状态时必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁住互斥量以后才能计算条件。
- int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *attr);
- int pthread_cond_destroy(pthread_cond_t *cond);
- int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
- int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex_t *mutex,
- struct timespec* timeout);
- int pthread_cond_signal(pthread_cond_t *cond);
- int pthread_cond_broadcast(pthread_cond_t *cond);
- //成功返回0,失败则返回错误编号
- #include <pthread.h>
struct msg* workq;- pthread_cond_t qready=PTHREAD_COND_INITIALIZER;
- pthread_mutex_t qlock=PTHREAD_MUTEX_INITIALIZER;
- void process_msg(void){
- struct msg* mp;
- for(;;){
- pthread_mutex_lock(&qlock);
- while(qlock==NULL){
- pthread_cond_wait(&qready,&qlock);
- }
- mp=workq;
- workq=mp->m_next;
- pthread_mutex_unlock(&qlock);
- }
- }
- void enqueue_msg(struct msg* mp){
- pthread_mutex_lock(&qlock);
- mp->m_next=workq;
- workq=mp;
- pthread_mutex_unlock(&qlock);
- pthread_cond_signal(&qready);
- }
《APUE》读书笔记第十一章-线程的更多相关文章
- 《Linux内核设计与实现》第五周读书笔记——第十一章
<Linux内核设计与实现>第五周读书笔记——第十一章 20135301张忻 估算学习时间:共2.5小时 读书:2.0 代码:0 作业:0 博客:0.5 实际学习时间:共3.0小时 读书: ...
- 《UNIX环境高级编程》(APUE) 笔记第十一章 - 线程
11 - 线程 Github 地址 1. 线程概念 典型的 UNIX进程 可以看成只有一个 控制线程 :一个进程在某一时刻只能做一件事情.有了 多个控制线程 ,就可以把进程设计成在某一时刻能够做不止一 ...
- 《利用python进行数据分析》读书笔记--第十一章 金融和经济数据应用(一)
自2005年开始,python在金融行业中的应用越来越多,这主要得益于越来越成熟的函数库(NumPy和pandas)以及大量经验丰富的程序员.许多机构发现python不仅非常适合成为交互式的分析环境, ...
- C primer plus 读书笔记第十一章
本章标题是字符串和字符串函数.主要是了解和字符串有关的函数. 1.字符串表示和字符串I/O 主要内容:字符串常量和字符串数组的初始化,对比了指针和字符串. 其中要注意的是,数组初始化是从静态存储区把一 ...
- APUE读书笔记-第13章-守护进程
第13章 守护进程 13.1 引言 *守护进程也称精灵进程(daemon)是生存期较长的一种进程.它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNI ...
- 《Unix环境高级编程》读书笔记 第11章-线程
1. 引言 了解如何使用多个控制线程在单进程环境中执行多个任务. 不管在什么情况下,只要单个资源需要在多个用户键共享,就必须处理一致性问题. 2. 线程概念 典型的Unix进程可以看成只有一个控制线程 ...
- 《Java并发编程实战》读书笔记-第2章 线程安全性
要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问. 修复多线程问题的方式: 不在线程之间共享该状态变量 将状态变量修改为不可变的变量 在访问状态变量时使用同步 ...
- APUE读书笔记-第17章-高级进程间通信
17.1 引言 *两种高级IPC:基于STREAMS的管道(STREAMS-based pipe)以及UNIX域套接字(UNIX domain socket)可以在进程间传送打开文件描述符.服务进程可 ...
- APUE读书笔记-第18章-终端I/O
18.1 引言 *终端I/O的用途很广泛,包括用于终端.计算机之间的直接连线.调制解调器以及打印机等等,所以终端I/O系统非常复杂 18.2 综述 *终端I/O有两种不同的工作模式: (1)规范模式输 ...
随机推荐
- 记录一下最近开发web移动前端的过程
两个项目 第一个是公司网站的移动端,我所在的公司是做某方面的新闻站的. 所以说页面基本是以一条条的新闻+图文混排为主,顶部有一个自动slider+触屏滑动的功能, 使用的是swipe插件,轻量,简洁非 ...
- 文成小盆友python-num4 装饰器,内置函数
一 .python 内置函数补充 chr() -- 返回所给参数对应的 ASCII 对应的字符,与ord()相反 # -*- coding:utf-8 -*- # Author:wencheng.z ...
- python中的model模板中的数据类型
mode对应的类型 见 : https://docs.djangoproject.com/en/1.8/ref/models/fields/ 命令行ipython查看 from django.db i ...
- [Python 3.x 官方文档翻译]Whetting Your Appetite 欢迎您的使用
If you do much work on computers, eventually you find that there’s some task you’d like to automate. ...
- python 3.5 格式化字符串输出
#!/usr/bin/env python #encoding: utf-8 #.strip('里面可以去掉字符串中两边的字符') name = input('name :').strip(' ') ...
- 遗传算法matlab实现
我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang 以下运用MATLAB实现遗传算法: clc clear %参数 a = 0 ; b = 4 ; e ...
- SQL语句优化技术分析
一.操作符优化 1.IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格.但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用 ...
- UITableView常用属性和方法 - 永不退缩的小白菜
UITableView常用属性和方法 - 永不退缩的小白菜 时间 2014-05-27 01:21:00 博客园精华区原文 http://www.cnblogs.com/zhaofucheng11 ...
- 安装AD15有问题多数是因为旧版本AD软件没有卸载干净,清理方法详解
论坛中总会看到有些朋友安装AD14.x,AD15.x后,使用不正常,多数情况是因为旧版本的AD软件没有卸载干净,安装新版本AD软件后,就会有问题.卸载和清理AD旧版本软件的方法如下(此方法只能解决卸载 ...
- qt http 上传文件
//Qt文件 QFile file("1.jpg"); if(!file.open (QIODevice::ReadOnly)){ qDebug()<<&quo ...