如何使用结构在多线程中拥有共享计数器?
How can I have a shared counter in multithreading using structs?
我对多线程很陌生,我试图在不使用全局变量的情况下增加一个共享计数器,我的目标是尝试最大化不同线程之间的并发性并增加变量直到我在参数中给出一个数字。 .. 对不起,如果这是一个蹩脚的问题,但我想在这里得到帮助,当我编译我的代码并 运行 它时,我得到一个分段错误......我认为错误在于我创建的变量计数和共享柜台!
#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].cnt
或 real[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
线。以适当的互斥方式访问共享变量很重要,即使是只读访问也是如此。
我对多线程很陌生,我试图在不使用全局变量的情况下增加一个共享计数器,我的目标是尝试最大化不同线程之间的并发性并增加变量直到我在参数中给出一个数字。 .. 对不起,如果这是一个蹩脚的问题,但我想在这里得到帮助,当我编译我的代码并 运行 它时,我得到一个分段错误......我认为错误在于我创建的变量计数和共享柜台!
#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].cnt
或real[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
线。以适当的互斥方式访问共享变量很重要,即使是只读访问也是如此。