C pthread锁上的程序旋转

C pthread锁上的程序旋转,c,multithreading,posix,critical-section,C,Multithreading,Posix,Critical Section,在这个练习中,我的头撞在墙上几个小时后,我被困在了那堵墙上。 首先,这是一个程序,设计用于查找和打印1到上限之间的所有素数,其中上限是一些用户输入。该设计是为了实现POSIX线程 在我的程序中,它成功运行,直到线程方法中的一个后续迭代。当它到达后面的迭代时,它会进入行pthread\u mutex\u lock(lock)和旋转,迫使我用Ctrl+z组合键杀死它。我一直使用的两个输入是1表示线程数,10表示上限。这个缺陷是可以复制的,因为每次我尝试它时都会发生。注意:虽然这段代码应该能够实现多个

在这个练习中,我的头撞在墙上几个小时后,我被困在了那堵墙上。 首先,这是一个程序,设计用于查找和打印1到
上限
之间的所有素数,其中上限是一些用户输入。该设计是为了实现POSIX线程

在我的程序中,它成功运行,直到线程方法中的一个后续迭代。当它到达后面的迭代时,它会进入行
pthread\u mutex\u lock(lock)和旋转,迫使我用Ctrl+z组合键杀死它。我一直使用的两个输入是
1
表示线程数,
10
表示上限。这个缺陷是可以复制的,因为每次我尝试它时都会发生。注意:虽然这段代码应该能够实现多个线程,但在添加更多线程之前,我希望它能够与一个子线程一起正常工作

#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);
}
#包括
#包括
#包括
int*numbermarker=NULL;
int*buffer=NULL;
int*checked=NULL;
int pullposition=0;
int placeposition=0;
pthread_mutex_t*锁;
室内天花板;
/*此方法将其中一个素数放置在缓冲区中。信息技术
提供了一种安全的方法来管理下一个值的放置位置*/
无效位置值(int值){
缓冲区[placeposition]=值;
placeposition++;
}
void*threadmethod(){
int i;
int k;
int l;
而第(1)款{
printf(“pull%d编号%d\n”,pullposition,buffer[pullposition]);
pthread_mutex_lock(锁);
printf(“FLAG\n”);
l=缓冲器[pullposition];
pullposition++;
printf(“pullTWO%d编号%d\n”,pullposition,buffer[pullposition-1]);
pthread_mutex_unlock(锁);

对于(k=l+1;k我已经尝试了您的代码,并且

void placevalue(int value)
{
buffer[placeposition] = value;
placeposition++;
}
placeposition
超出了
buffer
的大小。这会导致未定义的行为,一个非常合理的结果是互斥锁被破坏(即
malloc()
ed紧跟在
buffer
之后)


除此之外,还有一个竞争条件是
placevalue()
。但是,如果您使用的是单个工作线程,那么您(还没有)运行到它。

+1对于实际调试它并告诉我们暂停的位置,如果不先尝试自己,就无法说出人们询问了多少次。虽然可能不是解决方案,但我确实看到了大量随机数组访问。有没有可能您正在读取缓冲区的结尾并破坏互斥锁的内存位置,从而导致e stall?线程代码本身看起来很好,所以我正在寻找其他途径。我想这是一种可能性,但由于它是在堆中分配的,我不认为每次我运行程序时它都会覆盖锁。你没有在表达式
k%l
中检查
l==0
。当我运行它时e程序因被零除而崩溃。您的线程是否可能在未崩溃程序的情况下死亡,导致程序永远无法释放锁?您在main()的最后一个循环中有错误,错误地添加了
if(numbermarker[i]==0);
检查您的代码。我正在删除我的答案,因为这不是您询问的bug的原因。这可能是由于(k=l+1;kNPE的答案是正确的,但这不是placeposition超出缓冲区大小的原因。代码冗余地查找素数,因此它最终会写入2,3,5,7,7,9,5,7,7,9,9 |然后通过缓冲区写入7,9,9,以及最后的9(在我的系统中,行为未定义)最后写入锁并使其相信有9个锁“用户”。