免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 5129 | 回复: 29
打印 上一主题 下一主题

奇怪的问题,莫非这个就是Linux的信号灯惊群效应? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-12-10 15:19 |只看该作者 |倒序浏览
接受批评,把代码放上来:

  1. #ifndef __QUEUE__H
  2. #define        __QUEUE__H


  3. u_long        queue_create(void);

  4. void        queue_destroy(u_long q_id);

  5. int                getqueue_status(u_long q_id, struct eph_context ** context);

  6. int                putqueue_status(u_long q_id, struct eph_context * context);



  7. #endif        /* __QUEUE__H */

复制代码



  1. #include "precomp.h"
  2. #include "mempool.h"
  3. #include "queue.h"




  4. u_long queue_create()
  5. {
  6.         struct queue_handle * q_handle = NULL;


  7.         q_handle = (struct  queue_handle *)malloc(sizeof(struct queue_handle));
  8.         if (!q_handle)
  9.         {
  10.                 return -1;
  11.         }

  12.         if (sem_init(&q_handle->;queue_sem, 0, 0) == -1)
  13.         {
  14.                 free(q_handle);
  15.                 return -1;
  16.         }

  17.         if (pthread_mutex_init(&q_handle->;queue_lock, NULL) != 0)
  18.         {
  19.                 sem_destroy(&q_handle->;queue_sem);
  20.                 free(q_handle);
  21.                 return -1;
  22.         }
  23.        
  24.         q_handle->;context_front = NULL;
  25.         q_handle->;context_rear  = NULL;
  26.        
  27.         return (u_long)q_handle;       
  28. }/* end of queue_create        */



  29. void queue_destroy(u_long q_id)
  30. {
  31.         struct eph_context        * context = NULL;
  32.         struct queue_handle        * q_handle = NULL;


  33.         if (q_id <= 0)
  34.         {
  35.                 return;
  36.         }

  37.         q_handle = (struct queue_handle *)q_id;
  38.        
  39.         sem_destroy(&q_handle->;queue_sem);

  40.         pthread_mutex_lock(&q_handle->;queue_lock);
  41.         while (q_handle->;context_front)
  42.         {
  43.                 context = q_handle->;context_front;
  44.                 q_handle->;context_front = q_handle->;context_front->;next;
  45.                 context_pool_put(g_context_pool, context);
  46.         }
  47.         pthread_mutex_unlock(&q_handle->;queue_lock);
  48.        
  49.         pthread_mutex_destroy(&q_handle->;queue_lock);

  50.         free(q_handle);

  51.         return;
  52. }/* end of queue_destroy */



  53. int getqueue_status(u_long q_id, struct eph_context ** context)
  54. {
  55.         struct queue_handle * q_handle = NULL;


  56.         if (q_id <= 0)
  57.         {
  58.                 return -1;
  59.         }

  60.         q_handle = (struct queue_handle *)q_id;


  61.     while (1)
  62.     {
  63.             if (sem_wait(&q_handle->;queue_sem) == 0)
  64.             {
  65.                     break;
  66.             }
  67.     }

  68.        
  69.         pthread_mutex_lock(&q_handle->;queue_lock);
  70.         if (q_handle->;context_front != NULL)
  71.         {
  72.                 *context = q_handle->;context_front;
  73.                 if (q_handle->;context_front == q_handle->;context_rear)
  74.                 {
  75.                         q_handle->;context_front        = NULL;
  76.                         q_handle->;context_rear        = NULL;
  77.                 }
  78.                 else
  79.                 {
  80.                         q_handle->;context_front        = q_handle->;context_front->;next;
  81.                 }
  82.                 *context->;next = NULL;
  83.         }
  84.         else
  85.         {
  86.      /* 就是想不通为什么会执行到这里来 */
  87.         *context = NULL;
  88.         }
  89.         pthread_mutex_unlock(&q_handle->;queue_lock);
  90.        
  91.        
  92.         return 0;       
  93. }/* end of getqueue_status */




  94. int putqueue_status(u_long q_id, struct eph_context * context)
  95. {
  96.         struct queue_handle *q_handle = NULL;
  97.        
  98.        
  99.         if (q_id <= 0)
  100.         {
  101.                 return -1;
  102.         }
  103.                
  104.        
  105.         context->;next = NULL;
  106.         q_handle = (struct queue_handle *)q_id;
  107.        
  108.         pthread_mutex_lock(&q_handle->;queue_lock);
  109.         if (q_handle->;context_front == NULL)
  110.         {
  111.                 q_handle->;context_front = context;
  112.                 q_handle->;context_rear  = context;
  113.         }
  114.         else
  115.         {
  116.                 q_handle->;context_rear->;next = context;
  117.                 q_handle->;context_rear       = context;
  118.                
  119.         }
  120.         pthread_mutex_unlock(&q_handle->;queue_lock);
  121.        
  122.         sem_post(&q_handle->;queue_sem);

  123.         return 0;
  124. }/* end of putqueue_status */


复制代码


简单的说,就是我做了一个队列,ABCD线程调用getqueue_status函数阻塞住。E线程调用putqueue_status给队列里放一个东西,然后发出信号灯让ABCD中的一个线程返回,但是奇怪的是,在我的程序中,我竟然发现,有时候线程进去队列里取数据的时候,竟然执行到了 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;
};


开始以为是信号灯惊群效应,后来我就A线程getqueue_status,B线程putqueue_status,还是一样出现那个问题

论坛徽章:
0
2 [报告]
发表于 2004-12-10 15:29 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

如果说是惊群效应也不对啊。,
我就用A线程getqueue_status
用B线程putqueue_status

结果有时候还是会执行到
else
{
*context = NULL;
}

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
3 [报告]
发表于 2004-12-10 15:47 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

  1.         pthread_mutex_lock(&q_handle->;queue_lock);
  2.         if (q_handle->;context_front != NULL)
  3.         {
  4.                 *context = q_handle->;context_front;
  5.                 if (q_handle->;context_front == q_handle->;context_rear)
  6.                 {
  7.                         q_handle->;context_front        = NULL;
  8.                         q_handle->;context_rear        = NULL;
  9.                 }
  10.                 else
  11.                 {
  12.                         q_handle->;context_front        = q_handle->;context_front->;next;
  13.                 }
  14.                 *context->;next = NULL;
  15.         }
  16.         else
  17.         {
  18.                 *context = NULL;
  19.         }
  20.         pthread_mutex_unlock(&q_handle->;queue_lock);
复制代码

*context->;next=NULL;
不管队列后面有没有东西全置NULL,别的线程还能取到队列里的东西吗?
还有你从队列里取走后也没有释放资源的过程,时间长了,资源不耗光?

你可以用code把代码贴上来,不然别人懒得看!

论坛徽章:
0
4 [报告]
发表于 2004-12-10 15:58 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

原帖由 "yuxh" 发表:

不管队列后面有没有东西全置NULL,别的线程还能取到队列里的东西吗?
还有你从队列里取走后也没有释放资源的过程,时间长了,资源不耗光?

你可以用code把代码贴上来,不然别人懒得看!



啊,老大,我觉得这一段没错啊。。


  1.         pthread_mutex_lock(&q_handle->;queue_lock);
  2.         if (q_handle->;context_front != NULL)
  3.         {
  4. /* 队列不为空,将*context指向队列头 */
  5.                 *context = q_handle->;context_front;
  6.                 if (q_handle->;context_front == q_handle->;context_rear)
  7.                 {
  8. /* 如果队列里只有一个结点,将队列置空 */
  9.                         q_handle->;context_front        = NULL;
  10.                         q_handle->;context_rear        = NULL;
  11.                 }
  12.                 else
  13.                 {
  14. /* 队列里有多个结点, 将队列头结点指向队列头结点的下一个结点 */
  15.                         q_handle->;context_front        = q_handle->;context_front->;next;
  16.                 }
  17. /* 将原来的队列头结点(现在已经不在队列里了)的next指针置空 */
  18.                 *context->;next = NULL;
  19.         }
  20.         else
  21.         {
  22.                 *context = NULL;
  23.         }
  24.         pthread_mutex_unlock(&q_handle->;queue_lock);
复制代码



另外资源的问题,因为我是用的内存池方式管理,在程序开始的时候分配,程序退出的时候释放。

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
5 [报告]
发表于 2004-12-10 16:02 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

我指的是if语句里*context->;next不能置为NULL,应该是下一个节点
不然把前面q_handle->;context_front   = q_handle->;context_front->;next;又改回去了

论坛徽章:
0
6 [报告]
发表于 2004-12-10 16:09 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

*context->;next=NULL;  //编译能通过?

(*context) ->; next = NULL;

〉〉还有你从队列里取走后也没有释放资源的过程,时间长了,资源不耗光?
它取走了应该会在其他地方用到吧

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
7 [报告]
发表于 2004-12-10 16:15 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

我看错了
那也应该是(*context)->;next,你编译时没警告吗?

论坛徽章:
0
8 [报告]
发表于 2004-12-10 16:18 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

没有警告啊,,, 我用GCC编译的
我觉得*好优先级是要高一些吧?我把GCC加上 -wall参数看看

论坛徽章:
0
9 [报告]
发表于 2004-12-10 16:27 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

我把 *context->;next=NULL;
改为
(*context) ->; next = NULL;

问题依旧

论坛徽章:
0
10 [报告]
发表于 2004-12-10 16:38 |只看该作者

奇怪的问题,莫非这个就是Linux的信号灯惊群效应?

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP