【问题标题】:How can I have a shared counter in multithreading using structs?如何在使用结构的多线程中拥有一个共享计数器?
【发布时间】:2016-09-10 00:10:05
【问题描述】:

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

#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。

【问题讨论】:

  • 实现“共享计数器”的常用方法是将计数器作为参数传递给 pthread_create(即第二个参数)。然后您可以使用原子添加操作来增加计数器。
  • here:gote here; 标签写出循环并不是一个特别好的主意。在某些场合(一些但不是很多场合)适合使用 goto — 这不是少数场合之一。
  • 您实际上并没有验证您的代码是否获得了argv[1] 来转换;会不会是你忘了传递那个论点?
  • 然而,你的主要问题是你初始化了real[0].cnt,但你没有初始化real[1].cntreal[2].cnt,所以那些线程正在访问谁知道什么内存——可能是他们使用空指针,或者它可能是指向内存中任何位置的指针,无论分配与否,可写与否。你也错过了&lt;stdlib.h&gt;
  • 你能举个例子吗? @bruceg

标签: c multithreading struct counter


【解决方案1】:

在 cmets 中发现了一些问题:

  • 写出带有标签here:goto here; 的循环并不是一个特别好的主意。在某些场合(一些但不是很多场合)适合使用 goto — 这不是少数场合之一。
  • 您实际上并没有验证您的代码是否获得了argv[1] 来进行转换;会不会是你忘了传递那个论点?
  • 然而,你的主要问题是你初始化了real[0].cnt,但你没有初始化real[1].cntreal[2].cnt,所以那些线程正在访问谁知道什么内存——可能是他们使用空指针,或者它们可能是指向内存中任何位置的指针,无论是否已分配、是否对齐、是否可写。
  • 你也错过了&lt;stdlib.h&gt;
  • 您正在互斥范围之外测试*(est-&gt;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-&gt;cnt 的读取,我从同一命令行获得了输出 OVERALL 102。使用适当的互斥访问共享变量很重要,即使它是只读访问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 2011-10-20
    • 1970-01-01
    相关资源
    最近更新 更多