1

嗨,我正在研究 POSIX 线程,我有一个类似的工作

  • 我们有 5 个线程,每个线程将使用相同的函数分别打印 'a'、'b'、'c'、'd、'e'
  • 必须按字母顺序创建线程。
  • 每个字符必须在屏幕上打印 50 次
  • 'a' 只能在打印完所有 'c' 后打印
  • 'b' 只能在打印完所有 'd' 后才能打印
  • 'c' 只能在打印完所有 'd' 后打印

所以在我显示我的代码之前,我必须解释我做了什么。首先,我有 5 个全局变量(它们是标志,它们最初都设置为 1)并且我将它们分配给 pthread_create() 函数返回的值。然后在主函数中,我在加入线程之前使用了 if() 条件。但我想我正在尝试错误的方式。问题是我无法处理“在 thread_a 之前,thread_d 必须完成其工作”的过程。如果您能提供帮助并提出一些更好的想法,我将不胜感激。这是我的代码,

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

int counter = 0;

int flag_a = 1;
int flag_b = 1;
int flag_c = 1;
int flag_d = 1;
int flag_e = 1;

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

void* thread_function(void* str);
void print_char(char* ch);

int main(){

    pthread_t thread_a, thread_b, thread_c, thread_d, thread_e;

    char* a = "a";
    char* b = "b";
    char* c = "c";
    char* d = "d";
    char* e = "e";


    flag_a = pthread_create( &thread_a, NULL, thread_function, (void*) a );
    flag_b = pthread_create( &thread_b, NULL, thread_function, (void*) b );
    flag_c = pthread_create( &thread_c, NULL, thread_function, (void*) c );
    flag_d = pthread_create( &thread_d, NULL, thread_function, (void*) d );
    flag_e = pthread_create( &thread_e, NULL, thread_function, (void*) e );

    if(flag_c==0)
        pthread_join( thread_a, NULL );

    pthread_join( thread_b, NULL );

    if(flag_d==0)
        pthread_join( thread_c, NULL );

    if(flag_d==0)
        pthread_join( thread_d, NULL );

    pthread_join( thread_e, NULL );

    printf("\nCounter = %d\n", counter);

    return 0;
}

void* thread_function(void* str) {

    int i;
    char* msg = (char*) str;

        for(i=0; i<50; i++) {

            pthread_mutex_lock(&mymutex);
            counter++;  
            print_char(msg);
            pthread_mutex_unlock(&mymutex);

        }
    }

void print_char(char* ch){

    int i;

    for(i=0; i<1; i++) {
        printf("%s --> ", ch);
        fflush(stdout);
        sleep(1);
    }
}

编辑:我找到了一个可以正确打印字符的解决方案,但问题是我无法异步打印它们。我的意思是每当我运行代码时,它都有相同的输出,例如:

e-->d-->c-->b-->a (每个字符打印 50 次)

这是 thread_function() 的编辑部分

void* thread_function(void* str) {

    int i;
    char* msg = (char*) str;

        while( (strcmp(msg,"a") == 0) && (counter_c < 5) ){
        ;;
    }

        while( (strcmp(msg,"c") == 0) && (counter_d < 5) ){
        ;;
    }

        while( (strcmp(msg,"b") == 0) && (counter_d < 5) ){
        ;;
    }

        for(i=0; i<5; i++) {

            pthread_mutex_lock(&mymutex);               
            counter++;

                if( strcmp(msg,"d") == 0 )
                    counter_d++;

                if( strcmp(msg,"c") == 0 )
                    counter_c++;

            print_char(msg);
            pthread_mutex_unlock(&mymutex);

        }
    }
4

4 回答 4

1

从逻辑上讲,您有一个依赖图,并且您需要一种方法让每个线程a)在开始打印它的东西之前等待某些条件发生,并且b)发出它已经完成打印的信号,以便其他等待的线程可以开始。在 pthreads 中,这可以通过条件变量来完成. 因此,您可以做什么,而不是将指针传递给要打印的字符,而是将指针传递给包含要打印的字符的结构,在开始打印之前等待的条件变量(和关联的互斥体),以及另一个条件变量相关联的互斥体在完成时发出信号。然后在主线程中,在创建线程之前,您当然需要适当地设置所有这些结构,并且在创建线程之后,主线程应该发出那些位于末尾(或开头,取决于您如何看看它..) 的依赖链,以便启动整个过程。

有关如何使用条件变量的介绍,请参见例如https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

于 2012-10-06T19:03:56.260 回答
1

// 先打印 d 然后打印 b 或 c 在 c 完成后它会打印 a。然后 main 函数将等待

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

int counter = 0;

int flag_a = 1;
int flag_b = 1;
int flag_c = 1;
int flag_d = 1;
int flag_e = 1;

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

void* thread_function(void* str);
void print_char(char* ch);

int main(){

    pthread_t thread_a, thread_b, thread_c, thread_d, thread_e;

    char* a = "a";
    char* b = "b";
    char* c = "c";
    char* d = "d";
    char* e = "e";

    flag_d = pthread_create( &thread_d, NULL, thread_function, (void*) d );
        pthread_join( thread_d, NULL );
    flag_b = pthread_create( &thread_b, NULL, thread_function, (void*) b );
    flag_c = pthread_create( &thread_c, NULL, thread_function, (void*) c );

  pthread_join( thread_c, NULL );

    flag_a = pthread_create( &thread_a, NULL, thread_function, (void*) a );
    flag_e = pthread_create( &thread_e, NULL, thread_function, (void*) e );

    //if(flag_c==0)
     //   pthread_join( thread_a, NULL );

   // pthread_join( thread_b, NULL );

    //if(flag_d==0)
      //  pthread_join( thread_c, NULL );

//    if(flag_d==0)
  //      pthread_join( thread_d, NULL );

    //pthread_join( thread_e, NULL );

    printf("\nCounter = %d\n", counter);
pthread_exit(NULL);  //or you can join thread e before printf() statement 
    return 0;
}

void* thread_function(void* str) {

    int i;
    char* msg = (char*) str;

        for(i=0; i<50; i++) {

            pthread_mutex_lock(&mymutex);
            counter++;  
            print_char(msg);
            pthread_mutex_unlock(&mymutex);

        }
    }

void print_char(char* ch){

    int i;

    for(i=0; i<1; i++) {
        printf("%s --> ", ch);
        fflush(stdout);
  //      sleep(1);
    }
}
于 2012-10-06T20:26:22.133 回答
0

实际上,您想要的是在开始工作之前暂停线程,直到给定线程完成。

  • 线程 A:打印 A
  • 线程 B:打印 B 的
  • 线程 C:打印 C 的
  • 线程 D:打印 D's

在您的情况下,您希望 A 等待 C,B 和 C 等待 D 并启动 D。为此,您需要semaphores,因为 semaphore 会阻塞线程,直到它被注意到唤醒。

于 2012-10-06T19:03:43.140 回答
0

也许我误解了要求?伪:

Start Ethread('e'); // can run async, since no contraints on 'e'
Start Dthread('d'); // print 'd' and 
Join Dthread;       // wait for 'd' to finish
Start Bthread('b'); // now start on the 'b'
Start Cthread('c'); // and the 'c'
Join Cthread;       // but just wait for the 'c' to finish
Start Athread('a'); // and then print the 'a'

每个线程打印其传递的字符 50 次。如果通用输出例程需要互斥体,OK。

这不满足要求吗?

于 2012-10-06T19:52:12.033 回答