Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 避免线程间竞争条件的Peterson算法 细节:_C_Multithreading_Algorithm_Pthreads_Pthread Join - Fatal编程技术网

C 避免线程间竞争条件的Peterson算法 细节:

C 避免线程间竞争条件的Peterson算法 细节:,c,multithreading,algorithm,pthreads,pthread-join,C,Multithreading,Algorithm,Pthreads,Pthread Join,我正在实现下面的Peterson算法,以避免竞争条件。我想这样做的方式是声明一个全局整数变量,并创建线程1和线程2。每当线程有权访问全局变量时,它都应该打印一个并将其添加到全局变量计数器中。当线程2有权访问这个全局变量时,它应该打印b并向全局变量计数器添加一个。这应该一直持续到全局变量达到某个数字,比如说10。在这之后,我希望线程将最后一次添加到全局变量的两个线程中的哪个线程重置为1,并且两个线程都应该退出。到目前为止,我实现的代码基本上完成了这项工作,它避免了竞争条件,但当计数器达到极限时,我

我正在实现下面的Peterson算法,以避免竞争条件。我想这样做的方式是声明一个全局整数变量,并创建线程1和线程2。每当线程有权访问全局变量时,它都应该打印一个并将其添加到全局变量计数器中。当线程2有权访问这个全局变量时,它应该打印b并向全局变量计数器添加一个。这应该一直持续到全局变量达到某个数字,比如说10。在这之后,我希望线程将最后一次添加到全局变量的两个线程中的哪个线程重置为1,并且两个线程都应该退出。到目前为止,我实现的代码基本上完成了这项工作,它避免了竞争条件,但当计数器达到极限时,我不能同时退出两个线程

问题: 当计数器达到特定限制时,如何退出两个线程

退出线程的正确形式是什么,现在我正在使用exit,我认为它不是很有效

彼得森算法 我的代码: 编辑:我意识到我必须在将标志更改为false之前,将if语句(即检查计数器限制值)放在critical部分

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


int counter = 0;

int flag[2];
int turn;

void *func1(void *);
void *func2(void *);

int main(int argc,char *argv[]){

    pthread_t thread1,thread2;
    //int rt1,rt2;

    flag[0] = 0;
    flag[1] = 0;

    //rt1 = pthread_create(&thread1,NULL,&func1,"a");
    //rt2 = pthread_create(&thread2,NULL,&func2,"c");
    pthread_create(&thread1,NULL,&func1,"a");
    pthread_create(&thread2,NULL,&func2,"b");

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);

    return 0;
}// End of main function


void *func1(void *message){


    while(1){
        flag[0] = 1;
        turn = 1;
        while(flag[1] && turn == 1);
        printf("%s %d\n",(char *)message,counter);
        counter++;
        flag[0] = 0;        

        if(counter == 10){
            counter = 1;
            printf("exited at func1, with counter %d\n",counter);
            exit(0);
        }   
    }
    return 0;
}

void *func2(void *message){

    while(1){
        flag[1] = 1;
        turn = 0;
        while(flag[0] && turn == 0);
        printf("%s %d\n",(char *)message,counter);
        counter++;
        flag[1] = 0;

        if(counter == 10){
            counter = 1;
            printf("exited at func2, with counter %d\n",counter);
            exit(0);
        }
    }
    return 0;
}

显然,当一个线程重置全局计数器时,另一个线程可能永远不会看到全局计数器到达,例如10,因此它永远不会退出。如果您只是不重置全局计数器,并让它在找到全局计数器(例如10)时退出线程,该怎么办?如果确实要重置计数器,可以在父主线程中执行此操作,这也是定义全局计数器的地方


对于退出线程,您可以简单地从主线程函数返回,这将自行结束线程,在线程内调用pthread_exit,或者从主函数使用phtread_cancel。

这是一个典型的示例,可以多次看到,文献中的一个抽象算法是用C语言实现的,而不考虑这些算法所具备的先决条件。这里最重要的是变量操作的原子性,这是C和POSIX都不能保证的。所以你在这里尝试的东西不能像那样工作。现代的C语言,也就是C11,有原子数据类型和线程,你可以使用它们,但对于初学者来说,这通常不是那么容易理解的。@JensGustedt,那么关于如何实现该算法有什么建议吗?考虑什么?为什么要实现这个算法?这是文献中的一个理论算法,从那时起,大量的水从桥下流过。它与您正在使用的工具无关。POSIX线程有自己的同步工具,请使用它们。@JensGustedt这是任务的一部分。我应该把这个问题提出来,我想,我很害怕。他们应该明确更新自己的课程。要做到这一点,你必须寻找一个带有C库的编译器来实现原子,最近的gcc和clang应该提供这一点,并从那里开始;这是我回答的第一段。如果你错了,你不能期望第二部分正常工作。如果我这样做了,那么在执行线程之后,它永远不会返回,我必须用ctl+c杀死它。但我会尝试找出它,不要测试计数器==10,测试计数器>9;在您有机会测试该值之前,一个计数器可能会将其递增到10,另一个计数器可能会将其递增到11。
#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>


int counter = 0;

int flag[2];
int turn;

void *func1(void *);
void *func2(void *);

int main(int argc,char *argv[]){

    pthread_t thread1,thread2;
    //int rt1,rt2;

    flag[0] = 0;
    flag[1] = 0;

    //rt1 = pthread_create(&thread1,NULL,&func1,"a");
    //rt2 = pthread_create(&thread2,NULL,&func2,"c");
    pthread_create(&thread1,NULL,&func1,"a");
    pthread_create(&thread2,NULL,&func2,"b");

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);

    return 0;
}// End of main function


void *func1(void *message){


    while(1){
        flag[0] = 1;
        turn = 1;
        while(flag[1] && turn == 1);
        printf("%s %d\n",(char *)message,counter);
        counter++;
        flag[0] = 0;        

        if(counter == 10){
            counter = 1;
            printf("exited at func1, with counter %d\n",counter);
            exit(0);
        }   
    }
    return 0;
}

void *func2(void *message){

    while(1){
        flag[1] = 1;
        turn = 0;
        while(flag[0] && turn == 0);
        printf("%s %d\n",(char *)message,counter);
        counter++;
        flag[1] = 0;

        if(counter == 10){
            counter = 1;
            printf("exited at func2, with counter %d\n",counter);
            exit(0);
        }
    }
    return 0;
}