APUE figure 11.12 勘误 关于死锁解决办法的代码错误

虽然我自己很不愿意面对这个事实。。。但是它就是错了,完全解释不通

我把书中问题代码的源码放在blog最后,并和第三版APUE进行比较


比较可以发现第二版中有这样一段代码和第三不一样

第二版foo_find里面:

foo_find(int id) /* find a existing object */
{
    struct foo  *fp;
    int         idx;
    idx = HASH(fp);
    pthread_mutex_lock(&hashlock);
    for (fp = fh[idx]; fp != NULL; fp = fp->f_next) {
很明显的可以看出局部变量fp是没有初始化的第一次使用fp是在

idx = HASH(fp) 那么这个时候fp就是未定义的垃圾值,这么做显然是错误的


我在第三版里面看到的就不一样了

struct foo *
foo_find(int id) /* find an existing object */
{
        struct foo *fp;
        pthread_mutex_lock(&hashlock);
        for (fp = fh[HASH(id)]; fp != NULL; fp = fp->f_next) {
利用id 检索哈希列表并给fp赋值定义和赋有意义值之间并没有使用fp,符合程序设计意义



所以我觉得第二版这里就明显的错了。可能是作者这里只是概念性的给出解决方案,没有具体的做代码测试。书中并没有写出带main函数的测试代码。我写的blog笔记也一直在弥补这个遗憾,把很多作者没有写出测试的代码都测试一遍。尽量给出每个API的demo







APUE 第二版 figure11.12的源码:

#include <stdlib.h>
#include <pthread.h>
#define NHASH 29
#define HASH(fp) (((unsigned long)fp)%NHASH)
struct foo *fh[NHASH];
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;
struct foo {
    int             f_count; /* protected by hashlock */
    pthread_mutex_t f_lock;
    struct foo     *f_next; /* protected by hashlock */
    int             f_id;
    /* ... more stuff here ... */
};
struct foo *
foo_alloc(void) /* allocate the object */
{
    struct foo  *fp;
    int         idx;
    if ((fp = malloc(sizeof(struct foo))) != NULL) {
        fp->f_count = 1;
        if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
            free(fp);
            return(NULL);
        }
        idx = HASH(fp);
        pthread_mutex_lock(&hashlock);
        fp->f_next = fh[idx];
        fh[idx] = fp->f_next;
        pthread_mutex_lock(&fp->f_lock);
        pthread_mutex_unlock(&hashlock);
        /* ... continue initialization ... */
    }
    return(fp);
}
void
foo_hold(struct foo *fp) /* add a reference to the object */
{
    pthread_mutex_lock(&hashlock);
    fp->f_count++;
    pthread_mutex_unlock(&hashlock);
}
struct foo *
foo_find(int id) /* find a existing object */
{
    struct foo  *fp;
    int         idx;
    idx = HASH(fp);
    pthread_mutex_lock(&hashlock);
    for (fp = fh[idx]; fp != NULL; fp = fp->f_next) {
        if (fp->f_id == id) {
            fp->f_count++;
            break;
        }
    }
    pthread_mutex_unlock(&hashlock);
    return(fp);
}
void
foo_rele(struct foo *fp) /* release a reference to the object */
{
    struct foo  *tfp;
    int         idx;
    pthread_mutex_lock(&hashlock);
    if (--fp->f_count == 0) { /* last reference, remove from list */
        idx = HASH(fp);
        tfp = fh[idx];
        if (tfp == fp) {
            fh[idx] = fp->f_next;
        } else {
            while (tfp->f_next != fp)
                tfp = tfp->f_next;
            tfp->f_next = fp->f_next;
        }
        pthread_mutex_unlock(&hashlock);
        pthread_mutex_destroy(&fp->f_lock);
        free(fp);
    } else {
        pthread_mutex_unlock(&hashlock);
    }
}




第三版源码

#include <stdlib.h>
#include <pthread.h>
#define NHASH 29
#define HASH(id) (((unsigned long)id)%NHASH)
struct foo *fh[NHASH];
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;
struct foo {
        int  f_count; /* protected by hashlock */
        pthread_mutex_t f_lock;
        int  f_id;
        struct foo *f_next; /* protected by hashlock */
        /* ... more stuff here ... */
};


struct foo *
foo_alloc(int id) /* allocate the object */
{
        struct foo *fp;
        int  idx;
        if ((fp = malloc(sizeof(struct foo))) != NULL) {
                fp->f_count = 1;
                fp->f_id = id;
                if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
                        free(fp);
                        return(NULL);
                }
                idx = HASH(id);
                pthread_mutex_lock(&hashlock);
                fp->f_next = fh[idx];
                fh[idx] = fp;
                pthread_mutex_lock(&fp->f_lock);
                pthread_mutex_unlock(&hashlock);
                /* ... continue initialization ... */
                pthread_mutex_unlock(&fp->f_lock);
        }
        return(fp);
}


void
foo_hold(struct foo *fp) /* add a reference to the object */
{
        pthread_mutex_lock(&hashlock);
        fp->f_count++;
        pthread_mutex_unlock(&hashlock);
}


struct foo *
foo_find(int id) /* find an existing object */
{
        struct foo *fp;
        pthread_mutex_lock(&hashlock);
        for (fp = fh[HASH(id)]; fp != NULL; fp = fp->f_next) {
                if (fp->f_id == id) {
                        fp->f_count++;
                        break;
                }
        }
        pthread_mutex_unlock(&hashlock);
        return(fp);
}


void
foo_rele(struct foo *fp) /* release a reference to the object */
{
        struct foo *tfp;
        int  idx;
        pthread_mutex_lock(&hashlock);
        if (--fp->f_count == 0) { /* last reference, remove from list */
                idx = HASH(fp->f_id);
                tfp = fh[idx];
                if (tfp == fp) {
                fh[idx] = fp->f_next;
                }else {
                        while (tfp->f_next != fp)
                        tfp = tfp->f_next;
                        tfp->f_next = fp->f_next;
                }
        pthread_mutex_unlock(&hashlock);
        pthread_mutex_destroy(&fp->f_lock);
        free(fp);
        }else {
                pthread_mutex_unlock(&hashlock);
        }
}


如有错漏,欢迎交流指正。Thank you




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值