C++ 代码

多种手机平台开发-----让我们跟苹果一起红起来。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

临界区,信号量

Posted on 2010-08-22 23:01  蔡清华  阅读(1825)  评论(0编辑  收藏  举报

  最近在做某系统的某应用的PAL 层, 避免不了要和临界区、信号量打交道,本人就总结下:

  1.   掌握什么是信号量、消息队列、互斥量?

  信号量: 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。信号量可用于进程间或线程间。只要信号量的value大于0,其他线程就可以等待信号量成功,成功后信号量的value减一。若value值不大于0,则等待信号量阻塞,直到信号量释放释放后value值加一。
  互斥量: 互斥量是用在多线程互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。比如对全局变量的访问,有时要加锁,操作完了,再解锁。互斥量可用于线程间, 不可用于进程间。只要被锁住,其他任何线程都不可以访问被保护的资源。
  消息队列: 消息是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象(例如结构体等)。“消息队列”是在消息的传输过程中保存消息的容器。消息队列将消息从它的发送方中继到接收方时充当中转站的作用。

  

    锁机制:仅能表示“开”与“关”两种状态;开、关原语必须作为原子操作来进行;关锁原语中反复测试W状态,浪费了处理机的时间;锁机制只能解决互斥,不能用于同步。

    信号量机制:可用于解决锁机制解决不了的问题,能用于线程或者进程同步问题。以下为信号量机制模型:

    P操作:                                        V操作:

                                                   

 

   同步例子

     有A、B两进程,A进程向缓冲区写入操作,B进程负责读取并加工缓冲区的内容。 

      我们可以这样做,假设:

    信号量S1:中有否可供加工的信息,初始值为0

    信号量S2:缓冲区是否为空,初始值为1;

                                            

  2. 信号量机制在linux 上的实现:

  

代码
#include <pthread.h>

/// 线程互斥锁。
pthread_mutex_t mutex;
/// 线程条件变量。
pthread_cond_t  cond;

/**  
@brief :   int sem_p(int *sem)  对信号量进行 p 操作。 
    等待信号量成功后的操作,如果信号量 不大于0,则等待信号量阻塞。
@param[in,out]  sem  信号量。
@return 0:  表示函数执行正确;
@return -1: 表示函数执行错误。
*/
int sem_p(int *sem)
{
    
int ret;
    
// 信号量减1
    (*sem)--;
    
if(*sem < 0)
    {
        pthread_mutex_lock(
&mutex);
        ret 
= pthread_cond_wait(&cond,&mutex);
                pthread_mutex_unlock(
&mutex);

                
if(ret != 0)
                {
                        
return -1;
                }
    }

    
return 0;
}


/**
@brief    int sem_v(int *sem)  对信号量进行 v 操作。
@param[in,out] sem  信号量。
@return 0:  表示函数执行正确;
@return -1:  表示函数执行错误。
*/
int sem_v(int *sem)
{    
    
// 信号量增1
    (*sem)++;
    
if(*sem >= 0)
    {
// 只要信号量 >=0 其他线程就可以等待信号量成功。

        
// 唤醒堵塞在这个条件变量上的所有线程。
        if(pthread_cond_broadcast(&cond) != 0)
        {
            
return -1;
        }
    }
    
    
return 0;
}

/**
@brief       int sem_init(int *sem, int value)  对信号量进行初始化操作。
@param[out] sem  信号量。
@param      value 信号量初始值。
@return 0: 表示函数执行正确;
@return -1 :表示函数执行错误。
*/
int sem_init(int *sem, int value)
{
    
if(value < 0)
    {
        
return -1;
    }
    
else
    {
        
*sem = value;
        
return 0;
    }
}