免费注册 查看新帖 |

Chinaunix

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

[C] 多线程锁的问题 [复制链接]

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-09-03 11:16 |只看该作者 |倒序浏览
本帖最后由 lewy7 于 2014-09-03 14:00 编辑

请教各位看官,下面这段程序是不是多线程锁用得不对?

如果不用线程的试过,没出问题,但是用线程的话就core dumped,Program terminated with signal 6, Aborted.

(gdb) bt
#0  0x0000003866630265 in raise () from /lib64/libc.so.6
#1  0x0000003866631d10 in abort () from /lib64/libc.so.6
#2  0x000000386666a84b in __libc_message () from /lib64/libc.so.6
#3  0x00000038666722ef in _int_free () from /lib64/libc.so.6
#4  0x000000386667273b in free () from /lib64/libc.so.6
#5  0x00000000004014b8 in queue_del (ptr=0x12166010) at queue.c:134
#6  0x0000000000400cb5 in consume (parameter=0x12166010) at main.c:74
#7  0x00000038672064a7 in start_thread () from /lib64/libpthread.so.0
#8  0x00000038666d3c2d in clone () from /lib64/libc.so.6
  1. pthread_mutex_t locker= PTHREAD_MUTEX_INITIALIZER;
  2. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

  3. void produce(httpq_queue_t *que)
  4. {
  5.         char data[100];
  6.         int i=9999;
  7.         while(i-->0){
  8.                 pthread_mutex_lock(&locker);
  9.                 str_timestamp(data);   //取微秒级的时间字符串
  10.                 if( 0 > queue_push(que,i,(void *)data,strlen(data)+1)) //加入队列
  11.                 {
  12.                         fprintf(stderr, "Error: %s:%d\n", __FILE__, __LINE__);
  13.                 }
  14.                 pthread_cond_signal(&cond); //发送信号给consume线程
  15.                 pthread_mutex_unlock(&locker);
  16.         }
  17. }

  18. void *consume(void *parameter)
  19. {
  20.         char data[100];
  21.         int i=0;
  22.         int j;
  23.         httpq_queue_t *que;
  24.         que=(httpq_queue_t *)parameter;
  25.         httpq_quedata_t *container;
  26.         pthread_mutex_lock(&locker);
  27.         while(1){
  28.                 pthread_cond_wait(&cond, &locker);
  29.                 container=(httpq_quedata_t *)malloc(sizeof(httpq_quedata_t)*que->size);
  30.                 j=que->size;//当前队列总数
  31.                 while(j-- > 0)
  32.                 {
  33.                         queue_struct_pop(que,container+i);//复制出队列头数据
  34.                         queue_del(que);//删除队列头数据,这个地方段错误了
  35.                         i++;
  36.                 }
  37.                 free(container);//释放
  38.                 usleep(1000);
  39.                 pthread_mutex_unlock(&locker);
  40.         }
  41. }

  42. int main()
  43. {
  44.         httpq_queue_t *que;
  45.         que=NULL;
  46.         create_queue(&que,"quename",999999);//创建一个最大999999的队列
  47.        
  48.         pthread_mutex_init (&locker,NULL);
  49.         pthread_t consumer_thread;
  50.         pthread_create(&consumer_thread, NULL, consume, (void *)que);
  51.        
  52.         produce(que);
  53.         pthread_join(consumer_thread,NULL);

  54.         return 0;
  55. }
复制代码

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
2 [报告]
发表于 2014-09-03 11:24 |只看该作者
你lock在循环外,unlock在循环里,不匹配

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
3 [报告]
发表于 2014-09-03 12:17 |只看该作者
回复 2# hellioncu

    void *consume(void *parameter)

    pthread_mutex_lock(&locker);
放到循环里也是一样结果,段错误。

论坛徽章:
0
4 [报告]
发表于 2014-09-03 14:01 |只看该作者
像这种生产者和消费者的问题,尽量使用信号量,条件变量容易发生死锁。既然是queue_del发生段错误,那就到代码中看看是不是逻辑错了

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
5 [报告]
发表于 2014-09-03 14:17 |只看该作者
回复 4# jwj070524


     现在就是纠结在一个地方,如果改成单线程
     while(1){
            生产;
            消费;
     }
     这样,就不会有段错误了,所以怀疑是线程锁用的不对。或者说的多线程中使用free和malloc有问题?

论坛徽章:
6
酉鸡
日期:2013-11-04 15:30:02巳蛇
日期:2014-01-23 10:36:23双鱼座
日期:2014-01-23 13:08:332015亚冠之鹿岛鹿角
日期:2015-09-03 14:36:002015亚冠之武里南联
日期:2015-09-18 10:48:1315-16赛季CBA联赛之山西
日期:2016-05-05 00:05:33
6 [报告]
发表于 2014-09-03 15:13 |只看该作者
在发送信号的后面加个usleep(1000);试试

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
7 [报告]
发表于 2014-09-04 15:20 |只看该作者
本帖最后由 yulihua49 于 2014-09-04 15:30 编辑
lewy7 发表于 2014-09-03 11:16
请教各位看官,下面这段程序是不是多线程锁用得不对?

如果不用线程的试过,没出问题,但是用线程的话就 ...

用法,流程完全是错的,再看看书。

正确的生产者流程:
  1.          
  2.         pthread_mutex_lock(&threadLock);
  3.         release_buf(fnp,&threadQueue);
  4.         pthread_mutex_unlock(&threadLock);
  5.         pthread_cond_signal(&threadCond);
复制代码
正确的消费者流程:
  1.        pthread_mutex_lock(&threadLock);
  2.         tpp->status=1;
  3.         while(NULL==(fn_rec=queue_get(fn_buf,&threadQueue))) {
  4.                 if(threadEnd) break;
  5.                 tpp->status=0;//置等待标志
  6.                 pthread_cond_wait(&threadCond,&threadLock);
  7.                 if(!tidp) break;
  8.                 tpp->status=1;
  9.         }
  10.         pthread_mutex_unlock(&threadLock);
复制代码

论坛徽章:
5
技术图书徽章
日期:2014-04-09 08:57:34辰龙
日期:2014-07-29 12:41:38白羊座
日期:2014-08-08 08:29:10巳蛇
日期:2014-09-09 08:59:43酉鸡
日期:2014-10-10 13:49:00
8 [报告]
发表于 2014-09-04 15:45 |只看该作者
我怀疑你的队列操作有误, 循环第二次的时候挂掉的吧?

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
9 [报告]
发表于 2014-09-09 09:35 |只看该作者
回复 8# sanagi1987
果然是这个问题,谢谢大仙。
下面的代码跑起来没什么大问题了,结贴。
马丹的,看了gdb一点也不靠谱,害得我在free那里找找问题找了好久。

  1. pthread_mutex_t locker= PTHREAD_MUTEX_INITIALIZER;
  2. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

  3. void produce(httpq_queue_t *que)
  4. {
  5.         char data[100];
  6.         int i=9999;
  7.         while(i-->0){
  8.                 pthread_mutex_lock(&locker);
  9.                 str_timestamp(data);   //取微秒级的时间字符串
  10.                 if( 0 > queue_push(que,i,(void *)data,strlen(data)+1)) //加入队列
  11.                 {
  12.                         fprintf(stderr, "Error: %s:%d\n", __FILE__, __LINE__);
  13.                 }
  14.                 pthread_cond_signal(&cond); //发送信号给consume线程
  15.                 pthread_mutex_unlock(&locker);
  16.         }
  17. }

  18. void *consume(void *parameter)
  19. {
  20.         char data[100];
  21.         int i=0;
  22.         int j;
  23.         httpq_queue_t *que;
  24.         que=(httpq_queue_t *)parameter;
  25.         httpq_quedata_t *container;
  26.         
  27.         while(1){
  28.                 pthread_mutex_lock(&locker);
  29.                 while(que->size == 0){
  30.                         pthread_cond_wait(&cond, &locker);
  31.                 }
  32.                 container=(httpq_quedata_t *)malloc(sizeof(httpq_quedata_t)*que->size);
  33.                 j=que->size;//当前队列总数
  34.                [color=Red] i=0;//少了这个[/color]
  35.                 while(j-- > 0)
  36.                 {
  37.                         queue_struct_pop(que,container+i);//复制出队列头数据
  38.                         queue_del(que);//删除队列头数据,这个地方段错误了
  39.                         i++;
  40.                 }
  41.                 free(container);//释放
  42.                 usleep(1000);
  43.                 pthread_mutex_unlock(&locker);
  44.         }
  45. }

  46. int main()
  47. {
  48.         httpq_queue_t *que;
  49.         que=NULL;
  50.         create_queue(&que,"quename",999999);//创建一个最大999999的队列
  51.         
  52.         pthread_mutex_init (&locker,NULL);
  53.         pthread_t consumer_thread;
  54.         pthread_create(&consumer_thread, NULL, consume, (void *)que);
  55.         
  56.         produce(que);
  57.         pthread_join(consumer_thread,NULL);

  58.         return 0;
  59. }
复制代码

论坛徽章:
1
15-16赛季CBA联赛之深圳
日期:2016-02-17 16:12:23
10 [报告]
发表于 2014-09-09 09:38 |只看该作者
回复 7# yulihua49


    谢谢,参照的改了流程。不过
     pthread_mutex_unlock(&threadLock);
     pthread_cond_signal(&threadCond);
   这个好像反了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP