线程同步之信号量,代码实现方法2(条件变量+mutex互斥量)

来源:互联网 发布:linux 添加epel源 编辑:程序博客网 时间:2024/06/06 10:53

方法1使用了系统semaphore,经过封装完成了信号量的实现,

本文章为方法2,使用条件变量 + 系统互斥量mutex实现信号量semaphore,代码如下所示:

//semaphore.h#ifndef _SEMAPHORE_2_H__#define _SEMAPHORE_2_H__#include <pthread.h>using namespace std;typedef unsigned int uint32_t;struct internal{pthread_condattr_tm_condattr;pthread_mutex_tm_mutex;pthread_cond_tm_cond;intm_count;};/// \class CSemaphore 信号量类class CSemaphore {private:CSemaphore(CSemaphore const&);CSemaphore& operator=(CSemaphore const&);public:/// 构造函数,创建系统信号量,initCnt表示信号量的初始计数explicit CSemaphore(int initCnt = 0);/// 析构函数,销毁系统信号量~CSemaphore();/// 消费信号量,当信号量为0时线程再消费信号量,线程就会被阻塞,进入信号量等待队列的队尾/// \return pend操作后当前信号量计数int pend();/// 生产信号量,如果信号量为0时有线程生产信号量,会唤醒信号量其等待队列的第一个线程/// \return post操作后当前信号量计数int post();/// 消费信号量,当信号量为0时线程再消费信号量,线程就会被阻塞,直到超时(毫秒)/// \return >=0表示当前信号量计数,-1:表示超时int pend(uint32_t timeout);/// 尝试减少信号量,如果信号量已经为0则马上返回/// \return 0:信号量减少成功,-1:信号量减少失败int tryPend();private:struct internal* m_internal;};//class CSemaphore#endif

//semaphore.cpp#include "semaphore.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <time.h>#define PRINT_LINE_INFO \do {\printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);\}while(0);#define ATTR m_internal->m_condattr#define MUTEX m_internal->m_mutex#define COND m_internal->m_cond#define COUNT m_internal->m_countCSemaphore::CSemaphore(int initCnt):m_internal(new struct internal){PRINT_LINE_INFO;pthread_condattr_init(&ATTR);pthread_condattr_setclock(&ATTR, CLOCK_MONOTONIC);/*init a condition-variable to its default value*/pthread_cond_init(&COND, &ATTR);/*init a condition-variable*/pthread_mutex_init(&MUTEX, NULL);COUNT = initCnt;}CSemaphore::~CSemaphore(){PRINT_LINE_INFO;pthread_mutex_destroy(&MUTEX);pthread_cond_destroy(&COND);delete m_internal, m_internal = NULL;}int CSemaphore::pend(){PRINT_LINE_INFO;int ret = 0;pthread_mutex_lock(&MUTEX);while (COUNT == 0 && ret == 0){PRINT_LINE_INFO;ret = pthread_cond_wait(&COND, &MUTEX);}if (ret != 0){return -1;}COUNT = COUNT - 1;int cnt = COUNT;ret = pthread_mutex_unlock (&MUTEX);return (ret == 0) ? cnt : -1;}int CSemaphore::post(){PRINT_LINE_INFO;int ret = 0;pthread_mutex_lock(&MUTEX);pthread_cond_signal(&COND);COUNT = COUNT + 1;int cnt = COUNT;ret = pthread_mutex_unlock(&MUTEX);return (ret == 0) ? cnt : -1;}int CSemaphore::pend(uint32_t timeout){PRINT_LINE_INFO;int err = 0;struct timespec to={0};struct timespec now={0};if (clock_gettime(CLOCK_MONOTONIC, &now) == -1){fprintf (stderr, "clock_gettime failed, errno=%d, strerror=%s\n", errno, strerror(errno));return -1;}to.tv_sec = now.tv_sec + (now.tv_nsec + (timeout%1000L)*1000000L)/1000000000L + timeout/1000L;to.tv_nsec = (now.tv_nsec + (timeout % 1000L) * 1000000L) % 1000000000L;pthread_mutex_lock(&MUTEX);//超时时err != 0,此时while退出循环while (COUNT == 0 && 0 == err){PRINT_LINE_INFO;err = pthread_cond_timedwait(&COND, &MUTEX, &to);}if (0 == err)--COUNT;int cnt = COUNT;pthread_mutex_unlock(&MUTEX);return (err == 0) ? cnt : -1;}int CSemaphore::tryPend(){PRINT_LINE_INFO;int ret = -1;ret = pthread_mutex_trylock(&MUTEX);bool bzero = false; //可以加解锁,但是资源为0if (ret == 0){if (COUNT > 0) {COUNT--;bzero = false;} else {bzero = true;}ret = pthread_mutex_unlock (&MUTEX);}//资源为0,即使解锁成为也返回-1ret = bzero ? -1 : ret;return (ret == 0) ? 0 : -1;}int main(){CSemaphore sem(0);sem.pend(10 * 1000);sem.pend();}


最后的测试结果:


(完)

0 0