最近在做某系统的某应用的PAL 层, 避免不了要和临界区、信号量打交道,本人就总结下:
- 掌握什么是信号量、消息队列、互斥量?
信号量: 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。信号量可用于进程间或线程间。只要信号量的value大于0,其他线程就可以等待信号量成功,成功后信号量的value减一。若value值不大于0,则等待信号量阻塞,直到信号量释放释放后value值加一。
互斥量: 互斥量是用在多线程互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。比如对全局变量的访问,有时要加锁,操作完了,再解锁。互斥量可用于线程间, 不可用于进程间。只要被锁住,其他任何线程都不可以访问被保护的资源。
消息队列: 消息是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象(例如结构体等)。“消息队列”是在消息的传输过程中保存消息的容器。消息队列将消息从它的发送方中继到接收方时充当中转站的作用。
锁机制:仅能表示“开”与“关”两种状态;开、关原语必须作为原子操作来进行;关锁原语中反复测试W状态,浪费了处理机的时间;锁机制只能解决互斥,不能用于同步。
信号量机制:可用于解决锁机制解决不了的问题,能用于线程或者进程同步问题。以下为信号量机制模型:
P操作: V操作:
同步例子:
有A、B两进程,A进程向缓冲区写入操作,B进程负责读取并加工缓冲区的内容。
我们可以这样做,假设:
信号量S1:中有否可供加工的信息,初始值为0;
信号量S2:缓冲区是否为空,初始值为1;
2. 信号量机制在linux 上的实现:
/// 线程互斥锁。
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;
}
}