免费注册 查看新帖 |

Chinaunix

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

初学者处女贴:高手请看下怎么解除死锁,并进入threadfunc打印出节点号 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-23 10:24 |只看该作者 |倒序浏览
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct node{
        int n_number;
        struct node * n_next;
        }*head = NULL;
static void cleanup_handler(void *arg)
{
        printf("cleanup handler pf second thread\n");
        free(arg);
        (void)pthread_mutex_unlock(&mtx);
}
static void *thread_func(void *arg)
{
        struct node *p = NULL;
        pthread_cleanup_push(cleanup_handler,p);
        while(1)
              {
                pthread_mutex_lock(&mtx);
                while(head==NULL)
                        {
                                pthread_cond_wait(&cond,&mtx);
                                p = head;
                                head = head->n_next;
                                printf("Got%dfrom queue\n",p->n_number);
                                free(p);
                                pthread_mutex_unlock(&mtx);
                        }
        }
        pthread_cleanup_pop(1);
        return 0;
}
int main(void)
{
        pthread_t tid;
        int i;
        struct node *p;
        pthread_create(&tid,NULL,thread_func,NULL);
        for(i=0;i<10;i++)
{
                p=malloc(sizeof(struct node));
                p->n_number = i;
                pthread_mutex_lock(&mtx);
                p->n_next = head;
                head = p;
                pthread_cond_broadcast(&cond);
                pthread_mutex_unlock(&mtx);
                sleep(1);
        }

        printf("thread 1 wanna end the cancel thread 2.\n");
        pthread_cancel(tid);
        pthread_join(tid,NULL);
        printf("all done\n");
        return 0;
}
我是初学者网上看到了这个程序,试着运行了,发现死锁了,改了后没死锁了,但是thread_func怎么也打印不出来,郁闷。。。

论坛徽章:
0
2 [报告]
发表于 2011-11-23 10:28 |只看该作者
抬头查资料,然后想想自己要做什么,最后埋头苦编——但永远不要ctrl+c然后ctrl+v,因为你最终必定会自己为这些你一点都不了解的代码买单。

论坛徽章:
0
3 [报告]
发表于 2011-11-23 10:45 |只看该作者
回复 2# 狗蛋

在钻多线程编-锁,这里在while(1)后加sleep(2),首尾时加break,能接触死锁,但没期望的获得节点信息,能解释下吗

论坛徽章:
0
4 [报告]
发表于 2011-11-23 11:05 |只看该作者
不建议用别人代码学习基本知识。

建议想明白别人用锁来同步什么、保护什么,然后自己做——做之前不要看他的代码。

刚开始可以做简单些的,比如仅仅两线程为一个整数累加之类——别看简单,照样能让你碰壁。

然后,再去写复杂的,但必须是自己写。



比如,sleep和break为何能解除这段代码的“死锁”?为何解了死锁就调用不到打印语句?
会问这个,原因就是你根本是两眼一抹黑,瞎胡弄而已。

论坛徽章:
0
5 [报告]
发表于 2011-11-23 11:38 |只看该作者
回复 4# 狗蛋
应该是我表达有误,通过加break解除死锁,和能否因此打印结果是两码事。我认为在while(1)后加sleep能让主进程使head!=NULL,之后能让程序进第二层循环,打印出节点信息,但还是不行,这是我真正想问的

论坛徽章:
0
6 [报告]
发表于 2011-11-23 12:03 |只看该作者
我觉得你这代码写的有问题,首先,你第一次锁了head,用broadcast唤醒了,另一个线程,但是head可能还是被锁的。应该先解锁,在broadcast唤醒另一个线程,另一个线程在使用head的时候要给head加锁,用完再解锁。

论坛徽章:
0
7 [报告]
发表于 2011-11-23 12:08 |只看该作者
回复 6# ronaldohf
条件变量不是这么用的,必须在锁内

论坛徽章:
0
8 [报告]
发表于 2011-11-23 12:12 |只看该作者
回复 6# ronaldohf

呵呵,我搞错了

论坛徽章:
0
9 [报告]
发表于 2011-11-23 12:18 |只看该作者
本帖最后由 digdeep126 于 2011-11-23 12:39 编辑

兄弟,在main函数中的:pthread_create(&tid, NULL, thread_func, NULL);
后面加上sleep(2);就可以了:
  1. int main(void)
  2. {
  3.         pthread_t       tid;
  4.         struct node     *p;
  5.         int i;

  6.         pthread_create(&tid, NULL, thread_func, NULL);
  7.         sleep(2);
  8.         for(i=0; i<10; i++){
  9.                 p = malloc(sizeof(struct node));
  10.                 p->n_number = i;
  11.                 p->n_next = NULL;
  12.                 pthread_mutex_lock(&mtx);
  13.                 p->n_next = head;
  14.                 head = p;
  15.                 pthread_cond_broadcast(&cond);
  16.                 pthread_mutex_unlock(&mtx);
  17.                 sleep(1);
  18.         }

  19.         printf("thread 1 wanna end the cancel thread 2.\n");
  20.         pthread_cancel(tid);
  21.         pthread_join(tid, NULL);
  22.         printf("all done\n");

  23.         return 0;
  24. }
  25.                                       
复制代码
运行结果:
digdeep@ubuntu:~/pthread$ ./deadlock2
Got 0 from queue
Got 1 from queue
Got 2 from queue
Got 3 from queue
Got 4 from queue
Got 5 from queue
Got 6 from queue
Got 7 from queue
Got 8 from queue
Got 9 from queue
thread 1 wanna end the cancel thread 2.
cleanup handler pf second thread
all done
因为,static void *thread_func(void *arg)函数中的while(head == NULL)永远为假,无法进入这个while里面。
另外,你链表的操作很不规范。
另外,这是一个典型的“生产者-消费者”模型。

论坛徽章:
0
10 [报告]
发表于 2011-11-23 12:21 |只看该作者
回复 9# digdeep126


    所以我才说他这是瞎胡闹,是霰弹式编程,才拒绝回答具体问题……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP