c - 如何使用结构在多线程中拥有共享计数器?

标签 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。

最佳答案

评论中发现了一些问题:

  • 使用标签 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来自同一命令行。即使是只读访问,通过适当的互斥访问共享变量也很重要。

关于c - 如何使用结构在多线程中拥有共享计数器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39421268/

相关文章:

c - 未初始化的变量 - 堆栈检查

java - 强制单线程 ANN 训练

c# - 任务 - 如何确保 ContinueWith 操作是 STA 线程?

c++ - 数组(结构)的平均值

c - 在 C 中使用 realloc 按字符读取输入字符

c - scanf:检测到输入太长

c - 打印 C 字符串时出现不需要的字符

c++ - mbstowcs_s 的 Microsoft 实现是线程安全的吗?

c - 将字符串传递给 C 中的结构体

c - 为什么这段代码中的 var.name[i] 正在打印 stationto 值