免费互斥问题

时间:2011-05-02 10:29:05

标签: c++ mutex

嘿所有人,非常感谢任何有关我有一点问题的帮助。基本上我的程序工作正常,但没有通过所有必需的测试。显然问题不在于以下之一:

  • 您加入了您创建的所有主题
  • 你摧毁了你初始化的所有突变
  • 解锁所有锁定的瑕疵

任何人都可以看到我出错了吗?非常感谢任何帮助,谢谢你

   #include "counter.h"

/* ============================================================================
 * File-global variables
 * ========================================================================== */
static int ncounters = 0;
static struct counter *counters = NULL;

static int nthreads = 0;
static int *ninstructions = NULL;
static struct instruction **instructions = NULL;


/* ============================================================================
 * Operations
 * ========================================================================== */
static void
decrement(long long *n) {
    *n = *n-1;
}

static void
increment(long long *n) {
    *n = *n+1;
}

static void
mult2(long long *n) {
    long long s = 2;
    long long t = *n;
    long long q = t*s;
    *n = q;
}


/* ============================================================================
 * Helper functions
 * ========================================================================== */

int
quit(void) {
    int i;
    for (i=0; i<nthreads; ++i) {
        free (instructions[i]);
    }
    free (instructions);
    for (i=0; i<ncounters; ++i) {
        pthread_mutex_t *my = &(counters[i].mylock);
        pthread_mutex_destroy(my);
    }
    free (counters);
    free (ninstructions);
    return 0;
}

/* ============================================================================
 * Thread function
 * ========================================================================== */
static void *
worker_thread(void *arg) {
    int t = *((int*)arg);
    int l;
    for (l = 0; l<ninstructions[t]; ++l) {
        int y;
        struct instruction* curr = &instructions[t][l];
        pthread_mutex_lock(&curr->counter->mylock);
        for (y=0; y<curr->repetitions; ++y) {
            long long *g = &curr->counter->counter;
            (curr->work_fn)(g);
        }
        pthread_mutex_unlock(&curr->counter->mylock);
    }

    return NULL;
}


/* ============================================================================
 * Main function
 * ========================================================================== */
int
main(void) {
    if (scanf("%d", &ncounters) != 1 || ncounters < 1) {
        printf("error\n");
        return quit();
    }
    counters = (struct counter*)malloc(ncounters*sizeof(struct counter));


    if (scanf(" %d", &nthreads) != 1 || nthreads < 1) {
        printf("error\n");
        return quit();
    }
    ninstructions = (int *)malloc(nthreads*sizeof(int));
    instructions = (struct instruction**)malloc(nthreads*sizeof(struct instruction*));
    int i;
    for (i=0; i<nthreads; ++i) {

        if (scanf(" %d", &ninstructions[i]) != 1) {
            printf("error\n");
            return quit();
        }
        instructions[i] = (struct instruction*)malloc(ninstructions[i]*sizeof(struct instruction));
        int k;
        for (k=0; k<ninstructions[i]; ++k) {
            int c, r;
            char f;
            if (scanf(" %d %c %d", &c, &f, &r) != 3 || c>ncounters-1) {
                printf("error\n");
                return quit();
            }
            struct instruction* curr = &instructions[i][k];
            struct counter* currcp = &counters[c];
            pthread_mutex_init (&currcp->mylock, NULL);
            curr->counter = currcp;
            curr->repetitions = r;
            switch(f) {
                case 'I': 
                    curr->work_fn = increment;
                    break;
                case 'D':
                    curr->work_fn = decrement;
                    break;
                case '2':
                    curr->work_fn = mult2;
                    break;
                default:
                    printf("error\n");
                    return quit();
            }
        }
    }
    int w;
    pthread_t threadIDs[nthreads];
    int args[nthreads];
    for (w=0; w<nthreads; ++w) {
        args[w] = w;
        pthread_create(&threadIDs[w], NULL, worker_thread, (void *) &args[w]);
    }
    int u;
    for (u=0; u<nthreads; ++u) {
        pthread_join(threadIDs[u], NULL);   
    }
    int d;
    for (d=0; d<ncounters; ++d) {
        printf("%lld\n", counters[d].counter);
    }
    return quit();
}

和数据结构

#ifndef __COUNTER_H__
#define __COUNTER_H__

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>


/* counter data structure */ 
struct counter {
    pthread_mutex_t mylock;
   long long counter;            /* to store counter */
};

/* counter value */
struct instruction {
   struct counter *counter;      /* pointer to counter */
   int repetitions;              /* number of repetitions  */
   void (*work_fn)(long long *); /* function pointer to work function */
};

#endif

是的抱歉我认为没有格式可能有可能:

<number of counters>
<number of threads>
<instruction-sequence>
<instruction-sequence>
....
<number of instructions>
<instruction>
<instruction>
....

因此,对于每个指令序列,您都有一个由一个或多个计数器上的每个线程执行的指令列表。 即输入:

2
2
1
0 I 10
2
1 D 10
1 2 2

将产生结果:

10
-40

(只有三种指令类型:增量(I),减量(D),多次减少2(2) 指令的格式为:

<counter> <function> <repitition>

这有意义吗?

2 个答案:

答案 0 :(得分:1)

好吧,看起来你正在加入你创建的所有线程,并解锁你锁定的所有突变 - 这部分相当简单。

然而,考虑到第二个条件,突变体的产生和破坏之间似乎没有明显的相关性。

您每个指令调用pthread_mutex_init一次,而每个计数器调用pthread_mutex_destroy一次。我不认为指令数量等于计数器数量。

我想你每个计数器需要一个互斥锁。因此,按指令使用单个互斥锁是没有意义的。您可能需要一个初始化例程,它为每个计数器提供一个互斥锁,以镜像您的quit例程,该例程会破坏每个计数器的互斥锁。

答案 1 :(得分:0)

用我自己的输入

10
3
2
1 I 3
2 D 4
2
3 2 5
4 2 6
2
5 I 7
6 D 8

输出

$ ./t.exe < i
0
3
-4
0
0
7
-8
0
0
0

使用您的输入我得到了您的预期结果。问题是什么?

更新

  

问题是测试输入没有公开,所以我不知道测试我失败了

在这种情况下,进行单元测试输入和

  • 务必触摸边缘情况(边界条件)
  • 如果这是linux,则在valgrind下运行它们;这样,如果有任何泄露,您将收到通知。