POSIX Thread (5) – Synchronization
Bây giờ hãy xem xét một chương trình mà nó có kết quả không như chúng ta mong đợi.
thread2.c
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int myglobal;
void *thread_function(void *arg) {
int i,j;
for ( i=0; i<20; i++ ) {
j=myglobal;
j=j+1;
printf(".");
fflush(stdout);
sleep(1);
myglobal=j;
}
return NULL;
}
int main(void) {
pthread_t mythread;
int i;
if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {
printf("error creating thread.");
abort();
}
for ( i=0; i<20; i++) {
myglobal=myglobal+1;
printf("o");
fflush(stdout);
sleep(1);
}
if ( pthread_join ( mythread, NULL ) ) {
printf("error joining thread.");
abort();
}
printf("\nmyglobal equals %d\n",myglobal);
exit(0);
}
POSIX Thread (4) – No parents, no children
Nguồn: http://www.ibm.com/developerworks/linux/library/l-posix1.html?
Nếu bạn đã từng sử dụng system call fork(), bạn chắc chắn đã quen với khái niệm về parent và child processes. Khi một process tạo ra một process mới bằng cách sử dụng fork() thì process mới được xem như là child process và process nguyên thủy của nó là parent. Nó sẽ tạo ra một cây process có mối quan hệ với nhau và có thể tương tác với nhau; như chờ đợi cho child process kết thúc. Ví dụ hàm waitpid() sẽ nói cho process hiện tại chờ tất cả child processes kết thúc. Waitpid được sử dụng để implement một hàm “dọn dẹp” cho parent process.
Có một chút thú vị khi sử dụng POSIX threads. Những thuật ngữ như parent thread hay child thread không có bởi vì thực sự với POSIX thread thì một mô hình các mối quan hệ giữa các thread là không tồn tại. Khi một thread chính có thể tạo ra một thread mới và thread mới này cũng có thể tạo thêm một thread mới khác. Tuy nhiên thì không có gì nói rằng thread mới đó là “cháu” của main thread. POSIX thread sẽ coi tất cả các thread như là một cái pool (giống như queue) đơn lẻ mà mỗi phần tử là một thread ngang hàng nhau. Do đó khái niệm đợi một child thread không có ý nghĩa. Việc thiếu tính chất thế hệ này ngụ ý một điểm chính: nếu bạn muốn đợi một thread kết thúc thì bạn cần phải xác định thread nào bạn đợi bằng truyền chính xác tid vào pthread_join. Thư viện thread không thể làm điều này hộ chúng ta.
Đối với nhiều người thì điều này không phải là tin tốt vì nó có thể làm phức tạp chương trình có nhiều hơn hai threads. Đừng để điều đó là phiền chúng ta. Chuẩn POSIX thread cung cấp công cụ để chúng ta có thể quản lý nhiều thread một cách dễ dàng. Sự thực thì việc không có mối quan hệ parent/children mở ra một cách nghĩ sáng tạo. Ví dụ, nếu chúng ta có một thread gọi là thread 1 và thread 1 này tạo ra một thread khác là thread 2, thì không nhất thiết là bản thân thread 1 phải gọi pthread_join cho thread 2. Bất kỳ thread nào khác trong chương trình cũng có thể làm điều này. Nó cho phép những khả năng thú vị khác khi bạn viết những đoạn mã multithread khổng lồ. Ví dụ bạn có thể tạo một “dead list” toàn cục bao gồm tất cả những thread đã bị dừng lại và sau đó có một thread đặc biệt để “dọn dẹp” chúng, đơn giản chỉ là đợi một item được thêm vào trong list. Thread có nhiệm vụ dọn dẹp đó sẽ gọi pthread_join() để merge với chính nó. Bây giờ thì quá trình “dọn dẹp” có thể được kiểm soát gọn gằng và hiệu quả trong một thread đơn.
(Còn tiếp)
leave a comment