如何在使用结构的多线程中使用共享计数器?

时间:2016-09-10 00:10:06

标签: c multithreading struct counter

我是多线程的新手,我试图在不使用全局变量的情况下增加共享计数器,我的目标是尝试最大化不同线程之间的并发性并将变量递增,直到我在参数中给出的数字...对不起,如果是一个蹩脚的问题,但我想在这里帮助,当我编译我的代码并运行它我得到分段错误...我认为错误是在我创建的变量计数和共享计数器!

#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex;
typedef struct {
    long *cnt;  /* pointer to shared counter */
    long n;     /* no of times to increment */
    int nr;
    pthread_t id;       /* application-specific thread-id */
} targ_t;
void *sfun(void *arg) {
    targ_t *est = (targ_t *) arg;
    here:
    pthread_mutex_lock(&mutex);
    (*(est->cnt))++;
    pthread_mutex_unlock(&mutex);
    if(*(est->cnt)<est->n)
        goto here;
    return NULL;
}


int main(int argc, char *argv[]){
    targ_t real[3];
    int c=0;
    long count=0;
    real[0].cnt=&count;
    pthread_mutex_init(&mutex, NULL);
    for(c=0;c<3;c++){
        real[c].n=atoi(argv[1]);
        real[c].nr=c+1;
        pthread_create(&real[c].id,NULL,&sfun,&real[c]);
    }
    for(c=0;c<3;c++){
        pthread_join(real[c].id,NULL);
    }
    pthread_mutex_destroy(&mutex);
    printf("OVERALL %lu\n", count);

    return 0;
} 
TY提前。

1 个答案:

答案 0 :(得分:0)

评论中发现了许多问题:

  • 使用标签here:goto here;编写循环并不是一个特别好的主意。在适合使用goto时,有些场合(有些但不是很多场合) - 这不是极少数场合之一。
  • 您实际上并未验证您的代码是否已转换为argv[1];难道你忘了传递那个论点吗?
  • 但是,您的主要问题是初始化real[0].cnt但您没有初始化real[1].cntreal[2].cnt,因此这些线程正在访问谁知道什么内存 - 它可能是他们'重新使用空指针,或者它们可能指向内存中的任何位置,分配与否,对齐或不对齐,可写或不可写。
  • 您还缺少<stdlib.h>
  • 您正在排除互斥范围之外的*(est->cnt)

此代码修复了这些问题以及其他一些问题:

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct
{
    long *cnt;  /* pointer to shared counter */
    long n;     /* no of times to increment */
    int nr;
    pthread_t id;       /* application-specific thread-id */
} targ_t;

static void *sfun(void *arg)
{
    targ_t *est = (targ_t *)arg;
    while (1)
    {
        pthread_mutex_lock(&mutex);
        long cval = *est->cnt;
        if (cval < est->n)
            ++*est->cnt;
        pthread_mutex_unlock(&mutex);
        if (cval >= est->n)
            break;
    }
    return NULL;
}

int main(int argc, char *argv[])
{
    targ_t real[3];
    long count = 0;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s count\n", argv[0]);
        return(EXIT_FAILURE);
    }

    for (int c = 0; c < 3; c++)
    {
        real[c].cnt = &count;
        real[c].n = atoi(argv[1]);
        real[c].nr = c + 1;
        if (pthread_create(&real[c].id, NULL, &sfun, &real[c]) != 0)
            break;
    }

    for (int c = 0; c < 3; c++)
        pthread_join(real[c].id, NULL);

    pthread_mutex_destroy(&mutex);
    printf("OVERALL %lu\n", count);

    return 0;
}

运行时(例如,程序为pth59):

$ pth59 100
OVERALL 100
$

在移动测试之前(现在在cval上),以便在互斥锁的范围内完成*est->cnt的读取,我从同一命令行获得了输出OVERALL 102。即使它是只读访问权限,访问具有适当互斥的共享变量也很重要。