Hỏi về pthread_join

Mọi người cho mình hỏi về pthread với:

Mình đang tự tìm hiểu: vấn đề của mình là điều gì xảy ra khi pthread_create được gọi, nhưng sau đó pthread_join không được sử dụng.

Đây là code minh, họa, mình chưa giải thích được.

// tao 10 thread, moi thread co nhiem vu la in ra gia tri cua bien chua trong doi so cua chung va sau do thoat

#include <pthread.h>
#include <iostream>

/* Declaration of the function which will serve as an argument function for all the threads.*/
void* functionA (void*);

/* Declaration of the global variable which will get incremented by each of the threads in the common function `functionA`.*/
int counter = 0;

/* Declaration and initialization of the mutex variable which will protect the shared global variable `counter`.*/
pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER;

int main ()
{
    /* Declaring an array for 10 threads.*/
    pthread_t thread_id [10];

    /* Creating 10 threads with default attributes and the common function namely `functionA` for execution.*/
    for (int i = 0; i < 10; i++)
    {
        pthread_create (&thread_id [i], NULL, functionA, NULL);
    }

    std :: cout << "Final counter value: " << counter << "\n";
    return 0;
}

void* functionA (void* arg)
{
    /* `pthread_self ()` prints the thread ID of the currently calling thread.*/
    std :: cout << "Thread number: " << pthread_self () << "\n";
        
    pthread_mutex_lock (&mutexA);
    /* Each time this function gets called, the counter is incremented by the calling thread.*/
    counter++;
    pthread_mutex_unlock (&mutexA);

    return 0;
} 

Một số giá trị trả về của chương trình.

Cám ơn mọi người.

Bạn tạo thread mà không join thì lúc main() thoát, tất cả worker threads cũng sẽ kết thúc, ngay cả khi nó vẫn còn đang chạy. Join để block main thread và chờ đến khi worker trả về, rồi mới tiếp tục chạy. Ví dụ

void *worker(void *i)
{
  int *j = (int *) i;
  while (*j < 666)
    (*j)++;
  
  return 0;
}

int main()
{
  int i = 0;
  
  pthread_t p;
  pthread_create(&p, NULL, worker, &i);
  /* pthread_join(p, NULL); */
  
  printf("i = %i\n", i);
  
  return 0;
}

worker() sẽ được chạy ngay sau khi được pthread_create() khởi tạo, nhưng i = 0 vì main() sẽ kết thúc ngay sau đó -> kill cả worker thread giữa chừng. pthread_join() sẽ chờ worker() trả về rồi mới tiếp tục chạy main().

Nếu cần worker thread trả về kết quả sau xử lý thì join thread, không thì không join cũng được, thread sẽ tự động được cleanup khi main() kết thúc (trừ một số trường hợp cần manual free, ví dụ như FILE *, hoặc struct.

10 Likes

Cám ơn bạn vì câu trả lời.

Mình có một chút điều vẫn chưa rõ như sau:

Khi pthread_create(), sẽ tạo ra các thread độc lập với thread main. Như ví dụ của mình, thì có 10 cái worker, tại sao có những cái worker nó không in ID thread vậy hoặc là nó có in, sao nó không in đằng sau cái chữ Thread number vậy.

Còn vấn đề khi thread main kết thúc mà worker vẫn chưa xong thì nó vẫn kill vì không có join thì mình đã hiểu.

Cám ơn bạn.

Output không đồng đều do 10 workers chạy cùng lúc, nên output của chúng bị chồng (interleaved) lên nhau. stdout (std::cout) là của chung, nên ví dụ như khi worker 1 vẫn còn đang in ra stdout, worker 2 có thể được bắt đầu và viết ngay ra stdout vào lúc đó, tương tự với 10 workers.

Vấn đề do IO không được đồng bộ giữa các threads nên xảy ra race condition, chứ 10 workers vẫn là 10, vẫn chạy bình thường. Một cách giải quyết là wrap lại std::cout, lock/unlock mutex mỗi khi thực hiện IO, hệt như cách bạn làm với biến counter.

Thêm cái hình minh họa :cactus:

Click

9 Likes

Cám ơn bạn vì lời giải thích rất đầy đủ và bức ảnh rất thú vị và dễ hiểu.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?