嵌入式 互斥锁和条件变量基础常识

原创 2013年12月02日 14:57:15
前言

在学习posixipc编程的时候,遇到两个很重要的概念:互斥锁和条件变量,而且,在各种进程/线程之间的同步中的使用很多。所以今天就系统的整理了一下,主要的参考资料来自《UNIX网络编程卷2:进程间通信》

一、概述

在多线程或者多进程共享数据时,为了保证数据的完整性和正确性,,使用同步机制来实现。互斥锁和条件变量均是出自posix.1线程标准,可以被用来同步一个进程中的多个线程,还可以用来同步共享一块内存空间的多个进程。

比如典型的,在多处理线程编程生产者消-费者问题的时候,最值得注意的就是那些被共享的数据区,因为无法知道在哪个时候哪个线程在使用着这些共享数据,也无法预知哪个线程会先运行它,哪个线程后运行它,所以对这些资源做合理的分配和正确的使用是非常有必要的。在Linux中,提供了互斥锁、条件变量以及信号量来对共享资源进行保护。关于信号量在本篇中暂不做说明,只讨论互斥锁和条件变量在同步中的应用。

二、互斥锁

互斥锁(英文:Mutualexclusion,常缩写为Mutex)是一种常用在多线程编程中,防止多个线程对一个公共资源做读写操作的机制,以保证共享操作的数据的完整性。互斥锁也可以从字面意思来看,就是相互排斥的锁,它是最基本的进程或者线程间同步的方法,用来保护临界区,以保证任何时候只有一个线程或者进程在访问共享资源(如共享的代码段)。保护一个临界区的代码形式大致如下:

lock_the_mutex(...)

临界区

unlock_the_mutex(...)

posix的互斥锁被声明为pthread_mutex_t类型的变量。互斥锁也分为静态互斥锁和动态互斥锁两类,如果是静态互斥锁,常常会把它初始化为一个常值PTHREAD_MUTEX_INITIALIZER,就像这样:

static pthread_mutex_t lock =PTHREAD_MUTEX_INITIALIZER;

在内核中关于阻塞互斥锁的具体实现可以查看:include/linux/mutex.h这个文件。

如果互斥锁是动态分配的,比如通过malloc来分配的或者是分配在共享内存中,那么真正使用它之前一定要用pthread_mutex_init函数来对它做初始化。下面的三个函数是对互斥锁进行上锁和解锁:

#include<pthread.h>

int pthread_mutex_lock(pthread_mutex_t*mptr);

int pthread_mutex_trylock(pthread_mutex_t*mptr);

int pthread_mutex_unlock(pthread_mutex_t*mptr);

对以上三个函数,如果调用成功均返回0,失败返回相应的errno值。

互斥锁还有协作性,就是说,假如共享数据是一个链表,那么对该链表进行操作的所有线程都必须在其执行实际操作之前获取到该互斥锁。

三、互斥锁实现的生产者-消费者模型

以多生产者,单消费者的模型实践了互斥锁的作用。

问题描述:一个或者多个生产者(线程或者进程)创建着一个个的数据条目,然后这些条目由一个消费者(线程或者进程)处理。

实现方式:

1、只考虑多个生产者之间的同步互斥(producer_consumer1.c)

https://github.com/helianthuslulu/LINUX_IPC

2、生产者和消费者之间的同步,消费者采用轮询方式(producer_consumer2.c)

https://github.com/helianthuslulu/LINUX_IPC

四、条件变量

互斥锁的确能很好的实现进程/线程之间的同步问题,但是它是通过锁机制来实现的,就是仅仅通过加锁和解锁实现同步,效率比较低,于是就有了条件变量(ConditionVariable),条件变量允许一个进程或者是线程睡眠直到某个事件为止。

互斥锁用于上锁,而条件变量用于等待。条件变量是类型为pthread_cond_t的变量。具体来说条件变量可以适用的情况:在线程同步中存在这样的一种情况,某个线程A需要等待某个条件成立之后才能继续往下执行,如果当前这个条件不成立,那么该线程就阻塞等待,而如果某个时刻另一个线程B在执行的过程中使得这个条件成立了,那么就会唤醒相称A继续往下执行。

pthread库中用条件变量来阻塞等待一个条件,或者唤醒等待这个条件的进程。

条件变量操作相关的函数:

#include<pthread.h>

int pthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t*mutex);

int int pthread_cond_signal(pthread_cond_t*cond);

int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t*attr);

int pthread_cond_destroy(pthread_cond_t*cond);

int pthread_cond_timedwait(pthread_cond_t*cond,pthread_mutex_t mytex,const struct timespec*abstime);

int pthread_cond_broadcast(pthread_cond_t*cond);

 

pthread_cond_wait函数是用于条件变量的等待;

pthread_cond_signal用于条件变量的通知;

pthread_cond_init用户条件变量初始化;

pthread_cond_destroy用于条件变量的摧毁;

pthread_cond_timedwait也是用于条件变量的等待,不过它与pthread_cond_wait的区别在于,在pthread_cond_timewait中,如果等待时间达到或是超过所引用的参数*abstime,它将结束并返回错误ETIME

不过这里的“条件”可以是我们编程者自己选择,然后会在具体的代码实现中测试这种条件。

条件变量是利用线程间共享的全局变量来进行同步的一种机制,它的实现主要有两个动作:

(1)一个线程等待条件变量的成立而被挂起;

(2)由另外某个线程使得条件变量成立,给出条件成立的信号,唤醒该睡眠线程。

条件变量中条件的检测是在互斥锁的保护下进行的,所以说每个条件变量总是会有一个互斥锁与之关联。

在具体使用条件变量之前也是要进行初始化的,可以在单条语句中生成并且初始化一个条件变量,像这样:pthread_cond_t my_condition =PTHREAD_COND_INITIALIZER;

五、使生产者消费者模型来解释条件变量的使用

还是第三部分所提到的问题,不过使用了条件变量来通知消息,而不必在总是让消费者轮询,对之前的代码再次做了改进:

producer_consumer3.c

https://github.com/helianthuslulu/LINUX_IPC

相关文章推荐

多线程互斥锁和条件变量demo

  • 2016年06月13日 15:06
  • 18KB
  • 下载

pthread几个互斥锁和条件变量接口

pthread_cleanup_push/pthread_cleanup_pop: pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut)...
  • hui6075
  • hui6075
  • 2016年04月16日 17:46
  • 336

Linux C 信号、线程同步、线程互斥锁、线程条件变量

这一周学习 信号处理,线程pthread的创建、同步、阻塞、激发的情形信号量的处理函数#include "func.h" void sig(int signum) { // 同一个信号量最多执行两遍 ...

互斥锁与条件变量配合使用

互斥操作:   对共享资源的访问, 要对互斥量进行加锁, 如果互斥量已经上了锁, 调用线程会阻塞, 直到互斥量被解锁. 在完成了对共享资源的访问后, 要对互斥量进行解锁。     死锁主要发生在有...

linux网络编程二十七:多线程编程之信号量、互斥锁和条件变量

1. locker.h #ifndef __LOCKER_H__ #define __LOCKER_H__ #include #include #include class sem { p...

互斥锁与条件变量应用

互斥锁与条件变量配合使用,实现多线程对公共数据的访问。

Posix多线程编程(1) 互斥锁与条件变量

多线程 互斥锁 以及 条件变量的工作流程

Muduo库源码分析(5):互斥锁,条件变量类

互斥锁(muduo库简单的封装) 将muduo库的线程id的操作去除的简单版本 // 出错处理 #define MCHECK(ret) ({ __typeof__ (ret) errnum = (r...

线程 ,生产者. 消费者 互斥锁,条件变量

三个生产者(整数入列)线程、两个消费者线程(出列打印) 队列为空: 消费线程要睡眠等待  --需要生产者唤醒 队列为满(规定只有十个存储空间): 生产者要睡眠等待   --需要消费者唤醒 其他获锁、...

线程、互斥锁与条件变量实例理解

互斥锁:初始化进程锁:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restric...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 互斥锁和条件变量基础常识
举报原因:
原因补充:

(最多只允许输入30个字)