3

このエクササイズ中に頭を数時間壁にぶつけた後、私はその壁で立ち往生しています. まず、これは 1 から までのすべての素数を見つけて出力するように設計されたプログラムですceiling。ここで、上限はユーザー入力です。設計は、POSIX スレッドを実装することです。

私のプログラムでは、スレッドのメソッドの後の反復の 1 つまで正常に実行されます。後のイテレーションに到達すると、ラインにステップしてpthread_mutex_lock(lock);スピンし、Ctrl+z で強制終了させます。私が使用している2つの入力は1、スレッド数と10天井用です。この欠陥は、私が試したたびに発生するため、再現可能です。注: このコードは複数のスレッドを実装できるはずですが、追加する前に 1 つの子スレッドで正しく動作するようにしたいと考えています。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int* numbermarker = NULL;
int* buffer = NULL;
int* checked = NULL;
int pullposition = 0;
int placeposition = 0;
pthread_mutex_t* lock;
int ceiling;

/*This method places one of the primes in the buffer. It 
offers a safe way to manage where the next value will be placed*/
void placevalue(int value){
    buffer[placeposition] = value;
    placeposition++;
}


void* threadmethod(){   
    int i;
    int k;
    int l;
    while(1){   
        printf("pull %d   number %d \n",pullposition, buffer[pullposition]);
        pthread_mutex_lock(lock);
        printf("FLAG\n");
        l = buffer[pullposition];
        pullposition++;
        printf("pullTWO %d   number %d \n",pullposition, buffer[pullposition-1]);
        pthread_mutex_unlock(lock);
        for(k=l+1;k<=ceiling;k++){
            if(k%l){
                if(k%2){
                    checked[k]=1;
                    placevalue(k);
                }
            }
            else{
                numbermarker[k-1] = 1;
            }
        }
        int sum=0;
        for(i=0; i<ceiling; i++){
            if(numbermarker[i]){
                checked[i] = numbermarker[i];
            }
            printf("checked|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|\n",
checked[0], checked[1], checked[2], checked[3], checked[4], checked[5], checked[6], checked[7], checked[8], checked[9]); 
            sum += checked[i];
            printf("sum %d    ceiling %d\n",sum,ceiling);
        }
        printf("number |%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|\n",
numbermarker[0],    numbermarker[1],    numbermarker[2],    numbermarker[3],    numbermarker[4],    numbermarker[5],    numbermarker[6],    numbermarker[7],    numbermarker[8],    numbermarker[9]);
        if(sum == ceiling){
            return NULL;
        }
    }
}


int main()
{
    int numthreads;
    int i;

    printf("Enter number of threads: \n");
    scanf("%d", &numthreads);

    printf("Enter the highest value to check \n");
    scanf("%d", &ceiling);

    /*  This will hold 1's and 0's.
            1 = number has been checked or is
                    confirmed not to be a prime
            0 = number is a possible prime

            The idea behind these values is that the next
            prime can always be identified by the 0 with
            the lowest index
    */

    numbermarker = (int*)malloc(sizeof(int)*(ceiling));
    checked = (int*)malloc(sizeof(int)*(ceiling));

    /*This will hold the primes as they are found*/
    buffer = (int*)malloc(sizeof(int)*(ceiling));

    /*allocate space for the lock*/
    lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
    pthread_mutex_init(lock,NULL);

    for(i=0; i<ceiling; i++){
        if(i<1){
            numbermarker[i] = 1;
        }
        else{
            numbermarker[i] = 0;
        }
        checked[i]=0;
        buffer[i]=0;
        printf("%d \n",numbermarker[i]);
    }
    checked[0]=1;
    placevalue(2);
    printf("checked|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d|\n", checked[0], checked[1], checked[2], checked[3], checked[4], checked[5], checked[6], checked[7], checked[8], checked[9]);

    pthread_t **tid = (pthread_t **) malloc(sizeof(pthread_t *) * numthreads);

    for(i=0;i<numthreads;i++){
        tid[i] = (pthread_t *) malloc(sizeof(pthread_t));
    }

    for(i=0;i<numthreads;i++){
        if(pthread_create(tid[i],
                                            NULL,
                                            threadmethod,
                                            NULL)){
            printf("Could not create thread \n");
            exit(-1);
        }
    }       

    for(i=0;i<numthreads;i++){
        if(pthread_join(*tid[i], NULL)){
            printf("Error Joining with thread \n");
            exit(-1);
        }
        free(tid[i]);
    }

    free(tid);
    for(i=0;i<ceiling;i++){
        if(numbermarker[i] == 0){
            printf("%d sdfsddd \n", numbermarker[i]);
            printf("%d \n", i+1);
        }
    }

    free(buffer);
    free(numbermarker);
    buffer=NULL;
    numbermarker=NULL;
    return(0);
}
4

1 に答える 1

2

私はあなたのコードを試してみました

void placevalue(int value)
{
buffer[placeposition] = value;
placeposition++;
}

placepositionのサイズを超えていますbuffer。これにより、未定義の動作が発生します。非常に妥当な結果として、ミューテックスが破棄されます (これは のmalloc()直後に編集されますbuffer)。

その上、競合状態がplacevalue(). ただし、単一のワーカー スレッドを使用している場合は、(まだ) 実行していません。

于 2013-04-05T17:27:05.060 に答える