线程同步之信号量,代码实现方法2(条件变量+mutex互斥量)
2016-07-08 21:55
411 查看
方法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_t m_condattr;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
int m_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
最后的测试结果:
(完)
本文章为方法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_t m_condattr;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
int m_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_count CSemaphore::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; //可以加解锁,但是资源为0 if (ret == 0) { if (COUNT > 0) { COUNT--; bzero = false; } else { bzero = true; } ret = pthread_mutex_unlock (&MUTEX); } //资源为0,即使解锁成为也返回-1 ret = bzero ? -1 : ret; return (ret == 0) ? 0 : -1; } int main() { CSemaphore sem(0); sem.pend(10 * 1000); sem.pend(); }
最后的测试结果:
(完)
相关文章推荐
- 一点一点学C#2
- bzoj3034: Heaven Cow与God Bull
- 百度地图搜索经纬度代码
- [C#6] 6-表达式形式的成员函数
- python基础——使用dict和set
- [LeetCode 169]Majority Element: Moore Voting Algorithm
- 提高项目28-字符统计
- spring属性编辑器
- ASP.NET Core (一):简介
- Asp.net 控件用法汇总-RadioButtonList、DropDownList、button、Checkbox...
- C语言学习笔记_数组
- PHP面向对象知识总结
- 枚举,int ... X,ScheduledExecutorService
- 提高项目27.3暴力破解
- 用反射的方法获取一个类的信息
- 华为机试题—字符串压缩 c++
- 提高项目27.2解密
- H264 RTP封包原理(转载)
- 切莫让CDN缓存你的动态文件
- (巩固基础篇)排序算法:①插入排序②希尔排序③冒泡排序④选择排序⑤快速排序