Новичок в многопоточности здесь. Ровно на 5-й итерации (т. Е. При выполнении pthread_join (threadID [4], NULL) моя программа терпит неудачу из-за ошибки сегментации.
Я создаю несколько потоков для добавления / вычитания 1 из переменной счетчика для изучения условий гонки. Все работает плавно, пока я не попробую 5 потоков или больше. Ровно на последней итерации pthread_join (threadID [4], NULL) происходит сбой, и я не могу определить почему. Я уверен, что проблема здесь, поскольку я использовал операторы printf, чтобы увидеть, где он достигает, прежде чем сбой.
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <time.h>
int opt_threads;
int opt_iterations;
long nThreads;
long nIterations;
int opt_yield;
long long counter;
void add(long long *pointer, long long value) {
long long sum = *pointer + value;
if (opt_yield)
sched_yield();
*pointer = sum;
}
void *thread_worker(void * arg) {
long i;
for (i=0; i<nIterations; i++) {
add(&counter, 1);
add(&counter, -1);
}
return arg;
}
int main(int argc, char *argv[]) {
int c;
pthread_t *threadID = malloc(nThreads * sizeof(pthread_t));
if (threadID == NULL) {
fprintf(stderr, "Thread memory allocation failed\n");
exit(1);
}
static struct option long_options[] =
{
{"threads", required_argument, 0, 't'},
{"iterations", required_argument, 0, 'i'},
{"yield", no_argument, 0, 'y'},
{0,0,0,0}
};
while (1) {
c = getopt_long(argc, argv, "", long_options, NULL);
if (c==-1) break;
switch(c) {
case 't':
opt_threads = 1;
nThreads = atoi(optarg);
break;
case 'i':
opt_iterations = 1;
nIterations = atoi(optarg);
break;
case 'y':
opt_yield = 1;
break;
default:
fprintf(stderr, "Bad argument!\n");
exit(1);
}
}
counter = 0;
struct timespec start, finish;
int i;
//start clock
clock_gettime(CLOCK_MONOTONIC, &start);
//create
for (i=0; i < nThreads; i++) {
pthread_create(&threadID[i], NULL, &thread_worker, NULL);
printf("Created thread[%ld]\n", i);
}
//wait (join)
/*for (i=0; i < nThreads; i++) {
printf("Now i is %ld\n", i);
if (pthread_join(threadID[i], NULL) != 0)
fprintf(stdout,"ERRRRROOOORRRRRRRR\n");
}*/
pthread_join(threadID[0], NULL);
pthread_join(threadID[1], NULL);
pthread_join(threadID[2], NULL);
pthread_join(threadID[3], NULL);
pthread_join(threadID[4], NULL);
printf("about to end clock\n");
//finish clock
clock_gettime(CLOCK_MONOTONIC, &finish);
printf("finished clock\n");
long seconds = finish.tv_sec - start.tv_sec;
long ns = finish.tv_nsec - start.tv_nsec;
long runTime = (seconds + ns) * 1000000000L;
long nOperations = nThreads * nIterations * 2;
long avgOperations = runTime / nOperations;
long run_time = 1000000000L * (finish.tv_sec - start.tv_sec) + finish.tv_nsec - start.tv_nsec;
//Print
if (opt_yield == 0)
fprintf(stdout, "add-none, %ld, %ld, %lld, %ld, %lld, %lld\n", nThreads, nIterations, nOperations, run_time, run_time/nOperations, counter);
else if (opt_yield == 1)
fprintf(stdout, "add-yield-none, %ld, %ld, %lld, %ld, %lld, %lld\n",nThreads, nIterations, nOperations, run_time, run_time/nOperations, counter);
exit(0);
}
Я ожидаю, что программа сможет правильно дождаться 5-го потока, но она не работает из-за ошибки сегментации.
thread_worker
? вы можете опубликовать полный код? Я подозреваю, что что-то перезаписывает память, и в пятый раз наконец достигается какая-то критическая переменная, такая как указатель или индекс массива. - person Skaperen   schedule 05.08.2019nThreads
(помимо того, что вы сказали, а не того, что вы показали). Мы понятия не имеем, что такоеthreadID
. Это вероятно массив, но мы не знаем. Мы понятия не имеем, чтоthread_worker
делает. - person WhozCraig   schedule 05.08.2019pthread_join(threadID[0], NULL); pthread_join(threadID[1], NULL); pthread_join(threadID[2], NULL); pthread_join(threadID[3], NULL); pthread_join(threadID[4], NULL);
Это будет работать, только если параметр командной строки для потоков равен 5 - person user3629249   schedule 05.08.2019