c语言 - 避免线程之间竞争条件的彼得森算法



详细信息:

我正在实现彼得森算法(下图)以避免竞争条件。我想这样做的方法是声明一个全局整数变量,并创建线程一和线程二。每当线程可以访问全局变量时,它应该打印a并将一个添加到全局变量计数器中。当线程 2 可以访问此全局变量时,它应该打印b并将一个添加到全局变量计数器中。这应该持续到全局变量达到某个数字(假设 10)。之后,我希望线程(最后一次添加到全局变量的两个线程中的哪个线程)将全局变量重置为 1,并且两个线程都应该退出。到目前为止,我实现的代码可以完成这项工作,它避免了竞争条件,但是当计数器达到限制时,我无法退出两个线程。

问题:

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

  • 退出线程的正确形式是什么,现在我正在使用 exit(),我认为这不是很有效率。

彼得森算法

boolean flag [2];
int turn;
void P0()
{
    while (true) {
         flag [0] = true;
         turn = 1;
         while (flag [1] && turn == 1) /* do nothing */;
         /* critical section */;
         flag [0] = false;
         /* remainder */;
    }
}
void P1()
{
     while (true) {
          flag [1] = true;
          turn = 0;
          while (flag [0] && turn == 0) /* do nothing */;
          /* critical section */;
          flag [1] = false;
          /* remainder */
     }
}
 void main()
 {
       flag [0] = false;
       flag [1] = false;
       parbegin (P0, P1);
 }

我的代码:

编辑:我意识到我必须将 if 语句,即检查计数器限制值,应该放在关键部分(在它将标志更改为 false 之前)。

#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 %dn",(char *)message,counter);
        counter++;
        flag[0] = 0;        
        if(counter == 10){
            counter = 1;
            printf("exited at func1, with counter %dn",counter);
            exit(0);
        }   
    }
    return 0;
}
void *func2(void *message){
    while(1){
        flag[1] = 1;
        turn = 0;
        while(flag[0] && turn == 0);
        printf("%s %dn",(char *)message,counter);
        counter++;
        flag[1] = 0;
        if(counter == 10){
            counter = 1;
            printf("exited at func2, with counter %dn",counter);
            exit(0);
        }
    }
    return 0;
}

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

至于退出线程,您可以简单地从主线程函数返回(这将自行结束线程),从线程内部调用pthread_exit,或者您可以使用 main 函数中的phtread_cancel

最新更新