当前位置: 技术问答>linux和unix
linux的信号灯也有惊群效应?
来源: 互联网 发布时间:2015-08-27
本文导语: 这里贴代码看得不好看 到这里看 http://elssann.51.net/queue.h http://elssann.51.net/queue.c 简单的说,就是我做了一个队列,ABCD线程调用getqueue_status函数阻塞住。E线程调用putqueue_status给队列里放一个东西,然后发出信号灯让A...
这里贴代码看得不好看
到这里看
http://elssann.51.net/queue.h
http://elssann.51.net/queue.c
简单的说,就是我做了一个队列,ABCD线程调用getqueue_status函数阻塞住。E线程调用putqueue_status给队列里放一个东西,然后发出信号灯让A线程返回,但是奇怪的是,在我的程序中,我竟然发现,有时候线程进去队列里取数据的时候,竟然执行到了 getqueue_status函数的这一段,
else
{
*context = NULL;
}
奇怪啊,莫非这就是所谓的信号灯惊群效应?
补充一个结构
struct queue_handle
{
int queue_len;
sem_t queue_sem;
pthread_mutex_t queue_lock;
struct eph_context *context_front;
struct eph_context *context_rear;
};
到这里看
http://elssann.51.net/queue.h
http://elssann.51.net/queue.c
简单的说,就是我做了一个队列,ABCD线程调用getqueue_status函数阻塞住。E线程调用putqueue_status给队列里放一个东西,然后发出信号灯让A线程返回,但是奇怪的是,在我的程序中,我竟然发现,有时候线程进去队列里取数据的时候,竟然执行到了 getqueue_status函数的这一段,
else
{
*context = NULL;
}
奇怪啊,莫非这就是所谓的信号灯惊群效应?
补充一个结构
struct queue_handle
{
int queue_len;
sem_t queue_sem;
pthread_mutex_t queue_lock;
struct eph_context *context_front;
struct eph_context *context_rear;
};
|
好久没有看这个问题了,不好意思
你锁资源的时候只是判断了有没有线程在读,可是并没有判断有没有数据可读.我不知道是不是这个问题,你在自己检查一下临界资源的访问问题。
你锁资源的时候只是判断了有没有线程在读,可是并没有判断有没有数据可读.我不知道是不是这个问题,你在自己检查一下临界资源的访问问题。
|
我没有看源代码,不过请问:你的程序对你申请的队列进行异步访问的时候是不是已经对这个临界资源进行了互斥访问。
|
接上面的帖子。
如果没有进行互斥,当已经信号唤醒一个等待条件的时候,这个等待条件上的所有睡眠进程(线程)都会被唤醒,这个可能就是你说的惊群。
当一个线程已经消费了,队列里面的数据,另一个线程又进入的话当然得不到数据,这时应当有一个信号量来保证有数据可用的时候,才允许下一个消费进程进入临界区进行访问。
如果没有进行互斥,当已经信号唤醒一个等待条件的时候,这个等待条件上的所有睡眠进程(线程)都会被唤醒,这个可能就是你说的惊群。
当一个线程已经消费了,队列里面的数据,另一个线程又进入的话当然得不到数据,这时应当有一个信号量来保证有数据可用的时候,才允许下一个消费进程进入临界区进行访问。
|
while (1)
{
if (sem_wait(&q_handle->queue_sem) == 0)//首先所有线程睡眠等在这里
{
break;
}
}
pthread_mutex_lock(&q_handle->queue_lock);//唤醒后所有线程都来抢这个锁,得到的一个就继续执行,去取出队列中的数据,并且解锁返回。 但是注意这个时候其它线程就已经可以进入这段临界区,但是这个时候队列中已经没有数据可以使用了,所以自然就运行到了
else
{
*context = NULL;
}
这个地方。
{
if (sem_wait(&q_handle->queue_sem) == 0)//首先所有线程睡眠等在这里
{
break;
}
}
pthread_mutex_lock(&q_handle->queue_lock);//唤醒后所有线程都来抢这个锁,得到的一个就继续执行,去取出队列中的数据,并且解锁返回。 但是注意这个时候其它线程就已经可以进入这段临界区,但是这个时候队列中已经没有数据可以使用了,所以自然就运行到了
else
{
*context = NULL;
}
这个地方。