线程同步机制-互斥量

Posted hjj801006

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程同步机制-互斥量相关的知识,希望对你有一定的参考价值。

记录肖堃老师讲解的linux线程

1. linux系统中多任务(进程/线程)之间的关系

1> 独立:仅竞争CPU资源

2> 互斥:竞争除CPU外的其他资源

3> 同步:协调彼此运行的步调,保证协同运行的各个任务具有正确的执行次序

4> 通信:数据共享,彼此间传递数据或信息,以协同完成某项工作

 

 

2. 线程的数据共享

技术图片

 

线程间共享的数据和资源:进程代码段、进程中的全局变量(数据段)、进程打开的文件......

每个线程私有的数据和资源:线程ID,线程上下文(一组寄存器值的集合)、线程局部变量(存储在栈中)。

 

因此,线程之间可以通过进程中的全局变量,非常容易的实现通信和数据共享。

 

3. 任务的互斥关系

任务互斥-资源共享关系(间接相互制约关系)

任务本身之间不存在直接联系。一个任务正在使用某个系统资源,另外一个想用该资源的任务就必须等待,而不能同时使用

 

例如:全局变量存储在进程数据段中,被线程所共享。线程对全局变量的访问,要经历三个步骤:

1)将内存单元中的数据读入寄存器

2)对寄存器中的值进行运算

3)将寄存器中的值写回内存单元

 

技术图片

 

如上图所示:

两个线程A和B,共享同一个全局变量 i,两个线程对 i 都实现i+1的操作,在某种特定极端情况下,会产生一些意料不到的效果。

1> 线程A先执行,将内存中的 i 值读入到寄存器当中,此时i的值为5

2> 线程A对寄存器中的 i 值进行 加1 运算,此时寄存器值为6。同时线程B并发开始运行。由于线程A还没有将寄存器的值(register=6)写回内存单元,

  此时,线程B从内存中读取的 i 的值还是5。

3> 线程A将寄存器值写回内存(register=6)。线程B并发执行 i+1,  由于每个线程中,寄存器是私有的。因此,此时线程B中寄存器值执行的是(5+1=6)。

4> 线程B将寄存器值写回内存(register=6)

以上情况发现,本来的意图是 线程A执行 i+1后, 线程B执行再 i+1, 但是因为两个线程之间没有对共享资源访问的保护机制,所以导致对全局变量修改的丢失。

 

 

4. 临界资源

针对上面提到的情况,操作系统提出了临界资源的概念

临界资源:在一段时间内只允许一个任务(线程/进程)访问的资源。各个任务间应采取互斥方式,实现对资源的共享。

共享变量,打印机等属于临界资源。 

访问临界资源的那段代码被称为临界区

 

互斥量的作用:确保同一时间里 只有一个线程访问临界资源或进入临界区

互斥量(mutex)本质上是一把锁

1)在访问临界资源前,对互斥量进行加锁

2)在访问完成后对互斥量进行解锁

3)对互斥量加锁后,任何其他试图对互斥量加锁的线程将会被阻塞,直到互斥量被解锁为止

 

 

5.  互斥量使用

1)定义互斥量变量

  pthread_mutex_t mutex;

2)初始化互斥量

3)访问临界资源前对互斥量加锁

4)访问临界资源后对互斥量解锁

5)销毁互斥量变量

 

 

1)互斥量初始化

 头文件:pthread.h

静态初始化:

pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER

动态初始化:

int pthread_mutex_init( pthread_mutex_t *mutex, const pthread_mutexattr_t *attr )

参数与返回值:

  mutex - 指向互斥量的指针

  attr - 设置互斥量的属性,通常可采用默认属性,传入空指针(NULL)

  成功返回0,出错返回错误码

 

2)互斥量销毁: 互斥量使用完毕后,必须要对互斥量进行销毁,以释放资源

int pthread_mutex_destory( pthread_mutex_t *mutex )

参数与返回值:

  mutex - 指向互斥量的指针

  成功返回0,出错返回错误码

 

3)在对临界资源访问之前和访问之后,需要对互斥量进行加锁和解锁

int pthread_mutex_lock( pthread_mutex_t *mutex )

int pthread_mutex_unlock( pthread_mutex_t *mutex )

参数与返回值:

  mutex - 指向互斥量的指针

  成功返回0,出错返回错误码

当调用pthread_mutex_lock时,若互斥量已被加锁,则调用线程将被阻塞,直到可以完成加锁操作(其他线程解锁后)为止

 

4)互斥量非阻塞加锁

pthread_mutex_trylock( pthread_mutex_t *mutex ) 

调用该函数时,若互斥量未加锁,则对该互斥量进行加锁,返回0;若互斥量已加锁,则函数直接返回错误码EBUSY(不会阻塞调用线程)

 

以上是关于线程同步机制-互斥量的主要内容,如果未能解决你的问题,请参考以下文章

Linux 多线程同步机制:互斥量信号量条件变量

RTOS基础之线程间同步

线程同步——条件变量

线程同步——条件变量

进程/线程同步的方式和机制,进程间通信

线程同步的方式和机制