linux条件变量使用和与信号量的区别

近来在项目中用到条件变量和信号量做同步时,这一块一直都有了解,但也一直没有总结,这次总结一下,给大家提供点参考,也给自己留点纪念。

首先,关于信号量和条件变量的概念可以自行查看APUE,我这直接把APUE中的代码拿过来对比;

一,条件变量的使用:

#include <pthread.h>

struct msg {
    struct msg *m_next;
    /* ... more stuff here ... */
};
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 (workq == NULL)
            pthread_cond_wait(&qready, &qlock);
        mp = workq;
        workq = mp->m_next;
        pthread_mutex_unlock(&qlock);
        /* now process the message mp */
    }
}

void
enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);
}

当然,在触发条件变量时也可以用以下代码,两种方式各有优劣,具体可以参考:https://www.cnblogs.com/charlesblc/p/6143397.html

void
enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_cond_signal(&qready);
    pthread_mutex_unlock(&qlock);
}

二,工作中的使用:

typedef struct _STAT
{
    int b_stop;
    MDL_COND_T cond;
}STAT;
STAT g_enc_stat;
pthread_mutex_t mutex;
pthread_cond_t cond;//可以放在结构体里面
pthread_cond_init(&cond);
pthread_mutex_init(&mutex);
int dsp_thread_start(unsigned int trmn)
{
    
    pthread_mutex_lock(&mutex);
    ...
    if(1 == g_enc_stat.b_stop)
    {
   
      g_enc_stat.b_stop = 0;
      pthread_cond_signal(&cond); 
     
    }
    pthread_mutex_unlock(&mutex);
    return OK;
}


/**************************************
* @fn        
* @brief    
* @param   
* @return  
* @other 
***************************************/
int dsp_thread_stop(unsigned int trmn)
{
    
    pthread_mutex_lock(&mutex);
    ...
    g_enc_stat.b_stop = 1;
    pthread_mutex_unlock(&mutex);
    return OK;
}
void dsp_thread(void)
{
 for(;;)
{
pthread_mutex_lock(
&mutex);//不仅用于同步,还可以用于stop时互斥(线程执行时原子操作) if(g_enc_stat.b_stop) { pthread_cond_wait(&cond,&mutex); pthread_mutex_unlock(&mutex);//这个地方也可以不用,参考上述代码,直接执行下面 continue; } . . . pthread_mutex_unlock(&mutex);
} }

三,条件变量和信号量的区别:

(1)使用条件变量可以一次唤醒所有等待者,而这个信号量没有的功能,感觉是最大区别。

(2)信号量是有一个值(状态的),而条件变量是没有的,没有地方记录唤醒(发送信号)过多少次,也没有地方记录唤醒线程(wait返回)过多少次。从实现上来说一个信号量可以是用mutex + counter + condition variable实现的。因为信号量有一个状态,如果想精准的同步,那么信号量可能会有特殊的地方。信号量可以解决条件变量中存在的唤醒丢失问题。

(3)在Posix.1基本原理一文声称,有了互斥锁和条件变量还提供信号量的原因是:“本标准提供信号量的而主要目的是提供一种进程间同步的方式;这些进程可能共享也可能不共享内存区。互斥锁和条件变量是作为线程间的同步机制说明的;这些线程总是共享(某个)内存区。这两者都是已广泛使用了多年的同步方式。每组原语都特别适合于特定的问题”。尽管信号量的意图在于进程间同步,互斥锁和条件变量的意图在于线程间同步,但是信号量也可用于线程间,互斥锁和条件变量也可用于进程间。应当根据实际的情况进行决定。信号量最有用的场景是用以指明可用资源的数量。

经典的一句话:

 互斥量是信号量的一种特例,互斥量的本质是一把锁。A mutex is basically a lock that we set (lock) before accessing a shared resource and release (unlock) when we're done

四,互斥锁的巧用:

func a{
     lock;
     temp_time_id = m_time_id;
     m_time_id  = 0;
     unlock;//不仅减少锁的颗粒度,也能减少死锁,因为detach会等待一个定时器回调,但定时器回调也会加锁,类似于lock->A -> B->lock;
     if(0 != temp_time_id)  
         CTime::getinstance->detach(temp_time_id)    
}

 

posted @ 2020-01-08 23:12  月光下的脚步  阅读(4190)  评论(0编辑  收藏  举报