0
我編寫多線程程序Pi計算編號。這個數字被考慮,直到我不會發送處理SIGINT信號,然後所有的流程停止,我收到響應。但不幸的是,我無法理解一個錯誤,那麼當我發送信號時,有時我會收到錯誤的結果 - 例如4或3.17只有當我發送一個信號時纔會發生,迭代,一切都很正常。請幫忙。計算Pi多線程pthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
union params {
unsigned long long idx;
double sum;
};
#define module (1299709L)
#define num_steps_per_check (1)
unsigned long long *CntIter = NULL;
int num_threads = 0;
int is_interrupted = 0;
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
void* partial_sum(void *ptr);
void handlesgint(int sig);
int main(int argc, char* argv[])
{
double pi = 0;
unsigned long long i;
int opt;
pthread_t* ids;
union params* params;
int ret_code = 0;
// parse command line
if (1 == argc) {
fprintf(stderr, "Usage: %s -n num_threads\n", argv[0]);
exit (EXIT_FAILURE);
}
while ((opt = getopt(argc, argv, "n:")) != -1)
{
switch (opt)
{
case 'n':
num_threads = atoi(optarg);
if (num_threads <= 0 /*|| num_threads >= _POSIX_THREAD_THREADS_MAX*/) {
fprintf(stderr, "quantity of threads invalid\n");
exit(EXIT_FAILURE);
}
break;
default:
fprintf(stderr, "Usage: %s -n num_threads\n", argv[0]);
exit(EXIT_FAILURE);
}
}
// setting handler
if (SIG_ERR == signal(SIGINT, handlesgint)) {
perror("fail signal");
exit(EXIT_FAILURE);
}
// init memory
params = (union params *)malloc(num_threads * sizeof(union params));
CntIter = (unsigned long long *)calloc(num_threads, sizeof(long long));
ids = (pthread_t *)malloc(num_threads * sizeof(pthread_t));
// operation distribution
for (i = 0; i < num_threads; ++i) {
params[i].idx = i;
ret_code = pthread_create(ids + i, NULL, partial_sum, (void*)(params + i));
if (0 != ret_code) {
perror("pthread create");
exit (EXIT_FAILURE);
}
}
// joining
for (i = 0; i < num_threads; ++i) {
union params* res;
ret_code = pthread_join(ids[i], (void **)&res);
if (0 != ret_code) {
perror("pthread join");
exit (EXIT_FAILURE);
}
pi += res->sum;
}
pi *= 4.0;
printf ("\npi = %.16f\n", pi);
// free resources
free(params);
free(ids);
free(CntIter);
return (EXIT_SUCCESS);
}
void* partial_sum(void *ptr) {
double sum = 0;
int idx = ((union params *)ptr)->idx;
unsigned long long i = 0;
unsigned long long index = 0;
int ret_code = 0;
int terminating = 0;
int sign = 0;
sigset_t set;
// Block SIGINT
sigemptyset(&set);
sigaddset(&set, SIGINT);
ret_code = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (0 != ret_code) {
perror("fail sigmask");
exit(EXIT_FAILURE);
}
i = 0;
while (0 == terminating) {
index = num_threads * i + idx;
sign = (0 == index % 2 ? 1 : -1);
sum += sign * (1.0/(2 * index + 1));
CntIter[idx] = (CntIter[idx] + 1) % module;
//if (i == 1000000L) { - !!!If to uncomment it and not to send a signal, result correct
// break;
//}
// check flag
if (0 == (i % num_steps_per_check)) {
pthread_rwlock_rdlock(&rwlock);
if (1 == is_interrupted) {
terminating = 1;
}
pthread_rwlock_unlock(&rwlock);
}
++i;
}
((union params *)ptr)->sum = sum;
return ptr;
}
void handlesgint(int sig) {
pthread_rwlock_wrlock(&rwlock);
is_interrupted = 1;
pthread_rwlock_unlock(&rwlock);
}
你是說,如果計算停止早期,你沒有得到一個準確的結果。不是預期的嗎?例如。如果你只有一個線程,在一次迭代後停止,你會得到4. – ugoren
是的,你是對的。更正後的代碼我傳播了以下文章。非常感謝你。 – Dima00782