之前在这篇文章中(http://blog.csdn.net/weirancg/article/details/54095777),用信号量同步两个线程,用的是绝对时间,这种写法存在缺陷,即系统时钟被修改可能导致线程永远等待不到信号量释放。很可惜,在Linux中没有找到采用相对时间的信号量设置方法,所以,这里自己实现了一种采用相对时间的信号量等待方法。
/************************************************
** 本实例演示了两个线程,通过信号量进行同步,
** 这种方法简化了软件处理流程,可以用于请求应答机制。
************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <semaphore.h>
sem_t sem;
int sem_wait_relative_time(sem_t *sem, int sec, int nsec)
{
struct timespec old_time;
struct timespec new_time;
if ( clock_gettime( CLOCK_MONOTONIC, &old_time ) < 0 )
{
return -2;
}
while(1)
{
int ret = sem_trywait(sem);
if(ret == 0)
{
return 0;
}
else
{
if ( clock_gettime( CLOCK_MONOTONIC, &new_time ) < 0 )
{
return -2;
}
if(((old_time.tv_sec + sec) > new_time.tv_sec) || ((old_time.tv_nsec + nsec) > new_time.tv_nsec))
{
continue;
}
else
{
printf("event_thread wait timeout%d, %d!!!\n",old_time.tv_sec, new_time.tv_sec);
return -1;
}
}
}
}
int sem_wait_relative_second(sem_t *sem, int sec)
{
return sem_wait_relative_time(sem, sec, 0);
}
int sem_wait_relative_nsecond(sem_t *sem, int nsec)
{
return sem_wait_relative_time(sem, 0, nsec);
}
void event_thread(void *arg)
{
while(1)
{
printf("event_thread send req, wait ack...\n");//发送请求
int ret = sem_wait_relative_second(&sem, 3);//等待信号量,线程阻塞在这里,如果等待超时,则继续向后执行
if(ret == -1)
{
printf("event_thread wait timeout!!!\n\n");//等待信号量超时,但线程继续进行
}
else if(ret == 0)
{
printf("event_thread got ack!!!\n\n");//获得信号量,线程继续进行
}
else
{
printf("other err!!!\n\n");//获得信号量,线程继续进行
}
}
}
void io_thread(void *arg)
{
while(1)
{
sleep(4);
printf("io_thread got ack\n");//收到响应
sem_post(&sem);//发送信号量
printf("io_thread post sem\n");
}
}
//两个线程,一个事务线程,一个IO线程
int main(int argc, char *argv[])
{
pthread_t id1, id2;
pthread_t mon_th_id;
int ret;
ret = sem_init(&sem, 0, 0);
if(ret != 0)
{
perror("sem_init");
}
ret = pthread_create(&id1, NULL, (void *)event_thread, NULL);
if(ret != 0)
{
perror("pthread cread1");
}
ret = pthread_create(&id2, NULL, (void *)io_thread, NULL);
if(ret != 0)
{
perror("pthread cread2");
}
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
}