《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)规范模式输 ...
随机推荐
- Python实现合并排序MergeSort
def merge(sort_list, start, mid, end): left_list = sort_list[start:mid] right_list = sort_list[mid:e ...
- python学习第六天 条件判断和循环
总归来讲,学过C语言的同学,对条件判断和循环并不陌生.这次随笔只是普及一下python的条件判断和循环对应的语法而已. 条件判断: 不多说,直接贴代码: age = 23 if age >= 6 ...
- Python 升级
1.到官网下载对于的版本: 2.下载之后并解压出来,编译: tar xf python.xx.xx.tar.xz sudo mkdir /usr/local/python ./configure -- ...
- AES CBC 128的实现
原由 AES已经变成目前对称加密中最流行算法之一,AES可以使用128.192.和256位密钥,并且用128位分组加密和解密数据. 项目中需要使用AES对密码信息进行加密,由嵌入式设备使用C语言进行加 ...
- ScrollView嵌套listview 时根据内容动态设置listview高度
public static void setListViewHeightBasedOnChilds(ListView listView){ ListAdapter listAdapter = list ...
- Blogger安装最新文章 - Blog透视镜
在Blogger中,是没有最新文章的网页元素,不过倒是有信息提供这个小工具,其实这就是用来新增RSS网摘用的,其中就包含最新文章的Feed,所以只要在小工具中,加入RSS网摘Feed,就可以安装最新文 ...
- (一)一个简单的Web服务器
万丈高楼平地起,首先我们必须了解 超文本传输协议(HTTP) 以后才能够比较清晰的明白web服务器是怎么回事. 1. 浅析Http协议 HTTP是一种协议,允许web服务器和浏览器通过互联网进行来发送 ...
- TortoiseGit 使用教程
原文地址:http://blog.csdn.net/ethan_xue/article/details/7749639 git的使用越来越广泛 使用命令比较麻烦,下面讲解一下tortoisegit的使 ...
- 以Crypto++实现RSA加解密二进制数据
网上一大片讲怎么加解密字符串的,找了大半天也没找到讲加解密二进制数据的,于是自己研究了下,分享给大家. 加解密函数: #include <rsa.h> #include <randp ...
- 编程:C#调用Python模块
当下,C#与Python都是比较热门的计算机编程语言,他们各有优缺点,如果能让他们互相配合工作,那是多么美好的事情,今天我来讲解一下如何利用C#来调用Python. 如果让C#支持调用Python模块 ...