线程
线程是进程中的一个独立的执行流,由环境(包括寄存器集和程序计数器)和一系列要执行的置零组成。所有进程至少有一个线程组成,多线程的进程包括多个线程,所有线程共享为进程分配的公共地址空间,所以文本段(Text Segment)和数据段(Datan Segment)都是共享的,如果定义一个函数,在各线程中都可以调用,定义一个全局变量,在各个线程中都可以访问到。
从逻辑上看,多线程就就是一个应用程序中。由多个执行部分同时执行,但操作系统并没有将多个线程看做成多个独立的应用实现进程的调度,管理以及资源分配,一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
线程是系统调度的基本单位
进程是承担分配资源的一个实体
各线程共享资源
- 数据段各文本段
- 对全局变量的访问
- 文件描述符
- 每种信号的处理方式(SIG_IGN,SIG_DFL或自定义的信号处理函数)
- 当前的工作目录
- 用户的id和组id
各线程私有资源
1. 线程id
2. 上下文,包括寄存器的值,程序计数器和栈指针
3. 栈空间
4. error变量
5. 信号屏蔽字
6. 调度优先级
线程操作
- 创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
第一个参数thread是用来存储线程id,参数指向线程id的指针。如果在父子进程中创建多个线程,线程id值有可能相同,如果创建成功,在次函数中返回id,如果设置为NULL,将不会返回线程的标号符id
第二个参数 pthread_attr_t *attr用来设置线程属性,一般设置为NULL。
第三个参数是线程运行的代码其实地址,即在此线程中运行那段代码
第四个参数是运行函数的地址。
如果执行成功,返回0,失败返回-1.
2.线程终止
终止线程的三种情况
- 调用pthread_exit函数退出
- 调用pthread_cancel函数取消该线程
- 创建线程的进程退出或整个函数结束
- 其中一个线程执行了exec类函数执行了新的进程
#include <pthread.h>
void pthread_exit(void *retval);
该参数用来保存线程退出状态
3.线程等待
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
调用该函数的线程将挂起等待,直到id的线程终止。当含糊是返回时,处于等待的线程资源被回收。成功返回0,失败返回错误码。
第一个参数为等待线程的id
第二个参数用户自定义的指针,指向一个保存等待线程的完整退出状态的静态区。
线程的同步与互斥
互斥量
多个线程同时访问共享数据时会发生冲突。例如两个线程对同一个变量进行+1操作,当但两个线程同时进行+1操作时,最后结果只加了一次而非两次。
互斥以排他的方式共享数据被并发执行。我们引入的互斥锁。
互斥锁
互斥锁是一个二元变量,其状态为开锁与上锁,将某个共享资源与某个特定的互斥锁绑定后,对该共享资源的访问如下
- 在访问该资源前,首先申请该互斥锁,如果该互斥锁处于开锁状态,则申请到该锁对象,并立即占有该锁使该锁处于锁定状态,以防止其它线程访问该资源。如果该互斥锁处于锁定状态,默认阻塞等待。
- 只有锁定该互斥锁的进程才能释放该互斥锁。其它线程的释放操作无效。
互斥锁的基本操作
1.初始化和销毁互斥锁
定义互斥锁
pthread_mutex_t lock;
初始化和销毁互斥锁
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
//第一个参数mutex是指向初始化互斥锁的指针
//第二个参数mutexattr是指向属性对象的指针,该属性对象定义的初始化的互斥锁的属性。如果该指针为NULL,则使用默认的属性
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//销毁互斥锁,成功返回0,失败返回错误编码
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//PTHREAD_MUTEX_INITIALIZER,该宏初始化静态分配的互斥锁。对于静态分配初始化的互斥锁,不需要调用pthread_mutex_init()函数
2.申请互斥锁
如果一个线程要占用一共享资源,其必须先给互斥锁上锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
//以阻塞方式获得互斥锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//以非阻塞方式获得互斥锁
3.释放互斥锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//释放互斥锁释放操作只能由占有改该互斥锁的的线程来完成
条件变量
条件变量是线程的一种同步机制,条件变量给多个线程提供了一个会和的场所。
条件变量是用变量的形式来描述临界资源的是否在被访问,如果资源不能被访问,则申请互斥锁的执行流就会挂起到某个条件变量上,同时等待唤醒。
条件变量本身是被互斥量保护的,条件变量不能单独使用,必须配合互斥锁一起实现对资源的互斥访问。
基本操作
1.初始化,销毁条件变量
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//定义条件