簡體   English   中英

如何獲得正確的pthread執行順序

[英]How to get the correct order of execution of pthreads

我正在使用pthreads做直方圖,並且經過長時間的努力..最后它說:

Segmentation Fault (Core Dumped) 

不幸的是我有這條線

p=(struct1 *)malloc(sizeof(struct1)); 

從命令行將值獲取到結構變量后。.因此,這已清除。.感謝@DNT告訴我。

現在,當我嘗試執行以下程序時。.有時顯示輸出,有時輸出到which_bin函數並顯示以下內容

output type 1(which is not the correct output): 
Data = 0.000000 doesn't belong to a bin! 
Quitting

output type 2(almost the correct output of histo with time taken by threads): 
10.000-28.000: 
28.000-46.000: 
46.000-64.000: 
64.000-82.000: 
82.000-100.000: XXXXXXXXXX 
The code to be timed took 0.000415 seconds

我的問題是,為什么同一編在運行時顯示不同的輸出。我對它到底在尋找什么感到困惑。

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include "timer.h"
    void Usage(char prog_name[]);

    void Gen_data(void *p);
    void Gen_bins(void *p);
    int Which_bin(void *p);
    void Print_histo(void *p);


    void func(void *p);

    struct test
    {
     int bin_count, i, bin;
     float min_meas, max_meas;
     float* bin_maxes;
     int* bin_counts;
     int data_count;
     float* data;
    };

    typedef struct test struct1;

    int main(int argc, char* argv[])
    {
    double start, finish, elapsed;
    GET_TIME(start);

    struct1 *p;
    pthread_t th1, th2, th3;

    p=(struct1 *)malloc(sizeof(struct1));
    if (argc != 5)
        Usage(argv[0]);
    p->bin_count = strtol(argv[1], NULL, 10);
    p->min_meas = strtof(argv[2], NULL);
    p->max_meas = strtof(argv[3], NULL);
    p->data_count = strtol(argv[4], NULL, 10);

    p->bin_maxes = malloc(p->bin_count*sizeof(float));
    p->bin_counts = malloc(p->bin_count*sizeof(int));
    p->data = malloc(p->data_count*sizeof(float));


    pthread_create(&th1,NULL,(void*) Gen_data,(void*) p);
    pthread_create(&th2,NULL,(void*) Gen_bins,(void*) p);
    pthread_create(&th3,NULL,(void*) func,(void*) p);
    printf("Hi\n");


    pthread_join(th1,NULL);
    pthread_join(th2,NULL);
    pthread_join(th3,NULL);


    Print_histo(p);
    free(p->data);
    free(p->bin_maxes);
    free(p->bin_counts);

    GET_TIME(finish);
    elapsed = finish - start;
    printf("The code to be timed took %f seconds\n", elapsed);
    return 0;
}  /* main */

void func(void *p)
{
    int i;
    struct1 *args;
    args=(struct1*)p;

    for (i = 0; i < args->data_count; i++)
    {
        args->bin = Which_bin(args);
        args->bin_counts[args->bin]++;
    }

    #  ifdef DEBUG
        printf("bin_counts = ");
        for (i = 0; i < args->bin_count; i++)
            printf("%d ", args->bin_counts[i]);
        printf("\n");
    #  endif
}

/*---------------------------------------------------------------------
 * Function:  Usage
 * Purpose:   Print a message showing how to run program and quit
 * In arg:    prog_name:  the name of the program from the command line
 */
void Usage(char prog_name[] /* in */)
{
    fprintf(stderr, "usage: %s ", prog_name);
    fprintf(stderr, "<bin_count> <min_meas> <max_meas> <data_count>\n");
    exit(0);
}  /* Usage */


void Gen_data(void *p)
{
    struct1 *args;
    args=(struct1*)p;
    int i;
    srandom(0);
    for (i = 0; i < args->data_count; i++)
        args->data[i] = args->min_meas + (args->max_meas - args->min_meas)*random()/((double) RAND_MAX);

    #ifdef DEBUG
        printf("data = ");
        for (i = 0; i < args->data_count; i++)
            printf("%4.3f ", args->data[i]);
        printf("\n");
    #endif
} /* Gen_data */


void Gen_bins(void* p)
{
    struct1 *args;
    args=(struct1*)p;
    float bin_width;
    int   i;
    bin_width = (args->max_meas - args->min_meas)/args->bin_count;

    for (i = 0; i < args->bin_count; i++)
    {
        args->bin_maxes[i] = args->min_meas + (i+1)*bin_width;
        args->bin_counts[i] = 0;
    }

    #  ifdef DEBUG
        printf("bin_maxes = ");
        for (i = 0; i < args->bin_count; i++)
            printf("%4.3f ", args->bin_maxes[i]);
        printf("\n");
    #  endif
}

int Which_bin(void* p)
{
    struct1 *args;
    args=(struct1*)p;
    int bottom = 0, top =  args->bin_count-1;
    int mid;
    float bin_max, bin_min;

    while (bottom <= top)
    {
        mid = (bottom + top)/2;
        bin_max = args->bin_maxes[mid];
        bin_min = (mid == 0) ? args->min_meas: args->bin_maxes[mid-1];
        if (*(args->data) >= bin_max)
            bottom = mid+1;
        else if (*(args->data) < bin_min)
            top = mid-1;
        else
            return mid;
    }
    fprintf(stderr, "Data = %f doesn't belong to a bin!\n", args->data);
    fprintf(stderr, "Quitting\n");
    exit(-1);
}

void Print_histo(void *p)
{
    struct1 *args;
    args=(struct1*)p;
    int i, j;
    float bin_max, bin_min;

    for (i = 0; i < args->bin_count; i++)
    {
        bin_max = args->bin_maxes[i];
        bin_min = (i == 0) ? args->min_meas: args->bin_maxes[i-1];
        printf("%.3f-%.3f:\t", bin_min, bin_max);
        for (j = 0; j < args->bin_counts[i]; j++)
            printf("X");
        printf("\n");
    }
}

/* Print_histo */    #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "timer.h"
void Usage(char prog_name[]);

void Gen_data(void *p);
void Gen_bins(void *p);
int Which_bin(void *p);
void Print_histo(void *p);

void func(void *p);

pthread_mutex_t lock;
struct test
{
    int bin_count, i, bin;
    float min_meas, max_meas;
    float* bin_maxes;
    int* bin_counts;
    int data_count;
    float* data;
};

typedef struct test struct1;

int main(int argc, char* argv[])
{
    if (pthread_mutex_init(&lock, NULL) != 0)
    {
        printf("\n mutex init failed\n");
        return 1;
    }
    double start, finish, elapsed;
    GET_TIME(start);

    struct1 *p;
    pthread_t th1, th2, th3;

    p=(struct1 *)malloc(sizeof(struct1));
    if (argc != 5)
        Usage(argv[0]);
    p->bin_count = strtol(argv[1], NULL, 10);
    p->min_meas = strtof(argv[2], NULL);
    p->max_meas = strtof(argv[3], NULL);
    p->data_count = strtol(argv[4], NULL, 10);

    p->bin_maxes = malloc(p->bin_count*sizeof(float));
    p->bin_counts = malloc(p->bin_count*sizeof(int));
    p->data = malloc(p->data_count*sizeof(float));


    pthread_create(&th1,NULL,(void*) Gen_data,(void*) p);
    pthread_create(&th2,NULL,(void*) Gen_bins,(void*) p);
    pthread_create(&th3,NULL,(void*) func,(void*) p);
    printf("Hi\n");


    pthread_join(th1,NULL);
    pthread_join(th2,NULL);
    pthread_join(th3,NULL);


    Print_histo(p);
    free(p->data);
    free(p->bin_maxes);
    free(p->bin_counts);

    GET_TIME(finish);
    elapsed = finish - start;
    printf("The code to be timed took %f seconds\n", elapsed);
    return 0;
}  /* main */

void func(void *p)
{
    pthread_mutex_lock(&lock);
    printf("th3 from Gen_func\n");
    int i;
    struct1 *args;
    args=(struct1*)p;

    for (i = 0; i < args->data_count; i++)
    {
        args->bin = Which_bin(args);
        args->bin_counts[args->bin]++;
    }

    #  ifdef DEBUG
        printf("bin_counts = ");
        for (i = 0; i < args->bin_count; i++)
            printf("%d ", args->bin_counts[i]);
        printf("\n");
    #  endif
    pthread_mutex_unlock(&lock);
}

/*---------------------------------------------------------------------
 * Function:  Usage
 * Purpose:   Print a message showing how to run program and quit
 * In arg:    prog_name:  the name of the program from the command line
 */
void Usage(char prog_name[] /* in */)
{
    fprintf(stderr, "usage: %s ", prog_name);
    fprintf(stderr, "<bin_count> <min_meas> <max_meas> <data_count>\n");
    exit(0);
}  /* Usage */


void Gen_data(void *p)
{
    pthread_mutex_lock(&lock);
    printf("th1 from Gen_data\n");
    struct1 *args;
    args=(struct1*)p;
    int i;
    srandom(0);
    for (i = 0; i < args->data_count; i++)
        args->data[i] = args->min_meas + (args->max_meas - args->min_meas)*random()/((double) RAND_MAX);

    #ifdef DEBUG
        printf("data = ");
        for (i = 0; i < args->data_count; i++)
            printf("%4.3f ", args->data[i]);
        printf("\n");
    #endif
    pthread_mutex_unlock(&lock);
} /* Gen_data */


void Gen_bins(void* p)
{
    pthread_mutex_lock(&lock);
    printf("th2 from Gen_bins\n");
    struct1 *args;
    args=(struct1*)p;
    float bin_width;
    int   i;
    bin_width = (args->max_meas - args->min_meas)/args->bin_count;

    for (i = 0; i < args->bin_count; i++)
    {
        args->bin_maxes[i] = args->min_meas + (i+1)*bin_width;
        args->bin_counts[i] = 0;
    }

    #  ifdef DEBUG
        printf("bin_maxes = ");
        for (i = 0; i < args->bin_count; i++)
            printf("%4.3f ", args->bin_maxes[i]);
        printf("\n");
    #  endif
    pthread_mutex_unlock(&lock);
}

int Which_bin(void* p)
{
    struct1 *args;
    args=(struct1*)p;
    int bottom = 0, top =  args->bin_count-1;
    int mid;
    float bin_max, bin_min;

    while (bottom <= top)
    {
        mid = (bottom + top)/2;
        bin_max = args->bin_maxes[mid];
        bin_min = (mid == 0) ? args->min_meas: args->bin_maxes[mid-1];
        if (*(args->data) >= bin_max)
            bottom = mid+1;
        else if (*(args->data) < bin_min)
            top = mid-1;
        else
            return mid;
    }
    fprintf(stderr, "Data = %f doesn't belong to a bin!\n", args->data);
    fprintf(stderr, "Quitting\n");
    exit(-1);
}

void Print_histo(void *p)
{
    struct1 *args;
    args=(struct1*)p;
    int i, j;
    float bin_max, bin_min;

    for (i = 0; i < args->bin_count; i++)
    {
        bin_max = args->bin_maxes[i];
        bin_min = (i == 0) ? args->min_meas: args->bin_maxes[i-1];
        printf("%.3f-%.3f:\t", bin_min, bin_max);
        for (j = 0; j < args->bin_counts[i]; j++)
            printf("X");
        printf("\n");
    }
}

/* Print_histo */

我添加了幾行,以查看是否所有線程都在訪問其功能。

output 1:
Hi
th1 from Gen_data
th3 from Gen_func
Data = 0.000000 doesn't belong to a bin!
Quitting

在輸出1中,我可以看到未執行th2並且程序結束顯示錯誤。

output 2:
th1 from Gen_data
Hi
th2 from Gen_bins
th3 from Gen_func
10.000-28.000:
28.000-46.000:
46.000-64.000:
64.000-82.000:
82.000-100.000: XXXXXXXXXX
The code to be timed took 0.000348 seconds

在輸出2中,所有線程均被執行,輸出也被執行。

我感到困惑的是,為什么線程th2沒有被執行,以及如何確保所有線程都以正確的順序運行。

我想知道程序在邏輯上是否錯誤? 如果在這種情況下在邏輯上是錯誤的,為什么有時會顯示直方圖輸出..謝謝!

不能保證線程執行的順序。 在現代的多核處理器上,線程甚至可以並發執行。 不能保證Gen_bins線程在func線程之前完成。 由於您的線程訪問和操作相同的數據結構,結果如您所知是不可預測的。

盡管我認為此應用程序不需要線程,但請進行以下更改以確保線程按列出的順序執行。 更改:

pthread_create(&th1,NULL,(void*) Gen_data,(void*) p);
pthread_create(&th2,NULL,(void*) Gen_bins,(void*) p);
pthread_create(&th3,NULL,(void*) func,(void*) p);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
pthread_join(th3,NULL);

至:

pthread_create(&th1,NULL,(void*) Gen_data,(void*) p);
pthread_join(th1,NULL);
pthread_create(&th2,NULL,(void*) Gen_bins,(void*) p);
pthread_join(th2,NULL);
pthread_create(&th3,NULL,(void*) func,(void*) p);
pthread_join(th3,NULL);

這樣可以確保每個線程在下一個線程啟動之前執行並完成。 同樣,由於線程不是並發執行的,因此該程序不需要線程化,只會增加復雜性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM