Tải bản đầy đủ (.pdf) (26 trang)

Giới thiệu thư viện PTHREAD POSIX

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (116.83 KB, 26 trang )

1
Chương 3: Giới thiệu thư viện
PTHREAD POSIX
(POSIX, Portable Operating System Interface)


1) Hướng dẫn cài đặt PTHREAD POSIX với VC++ 6
*) Biên dịch
- Copy thư viện hàm pthread, có thư mục: Pre-built.2
- Thiết lập thư mục pthread\Pre-built.2\include;pthread\Pre-built.2\lib vào option
của VC++6 bằng cách chọn Tools->Option->Directories
- Copy pthreadVC2.dll vào C:\WINDOWS\system32
*) Chạy chương trình:
- Cấu hình project trong VC++: chọn Project ->Settings -> Link -> thêm
pthread.lib vào ô có tiêu đề
Object/library modules

2) Nhắc lại một số kiến thức quan trọng trong C++
- Con trỏ không kiểu
Con trỏ không kiểu là một loại con trỏ đặc biệt. Nó có thể trỏ tới một kiểu dữ liệu
bất kỳ, từ giá trị số cho tới một xâu kí tự. Hạn chế duy nhất của nó là dữ liệu được trỏ
tới không thể được tham chiếu tới một cách trực tiếp (chúng ta không thể dùng toán tử
tham chiếu * với chúng) vì độ dài của nó là không xác định và vì vậy chúng ta phải
dùng đến toán tử biến đổi kiểu dữ liệu hay phép gán để biến đổi con trỏ không kiểu
thành một con trỏ trỏ tới một loại dữ liệu cụ thể.
Một trong những tiện ích của nó là cho phép dùng tham số cho hàm mà không
cần chỉ rõ kiểu, vd:
#include <iostream.h>
void increase (void* data, int type)
{// integer increaser
switch (type)


{
case sizeof(char) : (*((char*)data))++; break;
case sizeof(short): (*((short*)data))++; break;
case sizeof(long) : (*((long*)data))++; break;
}
}
int main ()
{char a = 5;
short b = 9;
long c = 12;
increase (&a,sizeof(a));
increase (&b,sizeof(b));
6, 10, 13
2
increase (&c,sizeof(c));
cout << (int) a << ", " << b << ", " << c;
return 0;
}
sizeof là một toán tử của ngôn ngữ C++, nó trả về một giá trị hằng là kích thước tính
bằng byte của tham số truyền cho nó, ví dụ sizeof(char) bằng 1 vì kích thước của char là
1 byte.
- Con trỏ hàm
C++ cho phép thao tác với các con trỏ hàm. Tiện ích này cho phép sử dụng một
hàm như là một tham số của một hàm khác. Để có thể khai báo một con trỏ, trỏ tới một
hàm chúng ta phải khai báo nó như là khai báo một hàm nhưng phải bao trong một cặp
ngoặc đơn () tên của hàm và chèn dấu sao (*tenthamsocontroham) đằng trước.

Trong ví dụ này, minus là một con trỏ toàn cục trỏ tới một hàm có hai tham số kiểu
int, con trỏ này được gám để trỏ tới hàm subtraction, tất cả đều trên một dòng:
int (* minus)(int,int) = subtraction;


3) Giới thiệu các hàm chính của pthread
- Tạo thread
int pthread_create (pthread_t *thread, const pthread_attr_t *attr,
void* (*start_routine) (void *), void *arg) ;

thread: Một định danh ID duy nhất cho thread mới
attr: Lưu trữ các tham số của thread mới, mặc định là Null
start_routine: Địa chỉ của chương trình con mà chúng ra cần chạy trong thread
mới này
arg: Các tham số của chương trình con, mặc định là NULL
- Kết thúc thread
void pthread_exit (void *value_ptr);

- Thu hồi và kết thúc thread
int pthread_join( pthread_t inHandle, void
**outReturnValue);
Thực hiện việc thu hồi bộ nhớ và các thiết của thread có định danh
inHandle. Thread cha bị block, và phải chờ cho đến khi thread inHandle kết
thúc.
3



4) Ví dụ tạo lập và kết thúc thread
Chương trình chính (thread chính) tạo ra một thread con để làm một việc gì
đó cho mình. Trong ví dụ này chương trình sẽ in ra chữ “Hello, World!”, trong
đó thread con in “Hello, ”, còn thread chính in “World!”.

//1. Khai bao thu vien

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 2. Viet ham con tro; Se goi cac ham nay khi chung ta tao thread
void *print_hello(void *args)
{
printf("Hello, ");
fflush(stdout);
return(0);
}
// 3. Chuong trinh chinh
void main()
{// 3.1 Khai bao cac bien kieu pthread_t
pthread_t tid;
//3.2 Tao thread thuc hien cac nhiem ó cac ham con tro pthread_create()
pthread_create
pthread_join
pthread_exit
Thread cha
Thread con
4
if (pthread_create(&tid, NULL, print_hello, NULL))
{
perror("pthread_create() failed");
exit(1);
}
//3.3 Dong bo hoa thread chinh voi cac thread con pthread_join()
if (pthread_join(tid, NULL))
{perror("pthread_join() failed"); exit(1); }


printf(" World!\n");
fflush(stdout);
exit(0);
}

5) Trao đổi dữ liệu giữa thread chính với các thread con:
Mỗi thread sẽ thi hành một chương trình con, và chương trình chính có thể trao
đổi dữ liệu với nó. Thông thường thread chính sẽ giao nhiệm vụ và dữ liệu nguồn cho
các tiến trình con; các tiến trình con sau khi tính toán xong lại gửi kết quả về cho tiến
trình chính.
5.1) Truyền dữ liệu cho các thread thông qua tham số của pthread_create

VD 5.1: Truyền ID của các thread cho các chương trình con.
Các chương trình con in cac ID cua thread ra man hinh

Chuong trinh chinh tao ra N thread (cac thread con in ra chinh ID cua minh)

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define N_THREADS 6

void *BusyWork(void *myID)
{
printf("result = %d\n",(*((int*)myID)));
return (0);
}
int main (int argc, char *argv[])
{
pthread_t thread[N_THREADS];

int taskID[N_THREADS];

int rc, t, *status;

for(t=0; t<N_THREADS; t++)
5
{
//taskID[t]=t;
//printf("Creating thread %d\n", taskID[t]);
rc = pthread_create(&thread[t], NULL, BusyWork, &t);
//rc = pthread_create(&thread[t], NULL, BusyWork, &taskID[t]);
if (rc)
{
printf("ERROR; return code from pthread_create()is %d\n", rc);
exit(-1);
}
}

for(t=0; t<N_THREADS; t++)
{
rc = pthread_join(thread[t], NULL);
if (rc)
{
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
}

VD 5.2: Truyền dữ liệu có cấu trúc


#include <pthread.h>
#include <stdio.h>
#include <windows.h>
#define N_THREADS 3
struct Data
{
int thread_id, sum;
char *message;
};

char *messages[N_THREADS];

Data thread_data_array[N_THREADS];

void *PrintHello1(void *threadid)
{ int *id_ptr, taskid;
Sleep(10);
id_ptr = (int *) threadid;
6
taskid = *id_ptr;
printf("Thread %d: %s\n", taskid, messages[taskid]);
pthread_exit(NULL);
return(0);
}
//Tham so thuc su là dữ liệu kiểu cấu trúc Data
void *PrintHello2(void *threadata)
{
Data *data_ptr,data;
Sleep(10);

data_ptr = (Data *) threadata;
data = *data_ptr;
printf("Thread %d: Sum %d: %s\n", data.thread_id,data.sum , data.message);
pthread_exit(NULL);
return(0);
}

int main(int argc, char *argv[])
{ pthread_t threads[N_THREADS];
int *taskids[N_THREADS];
int rc, t;
int sum;
// Khoi tao
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";

for(t=0;t<N_THREADS;t++)
{
taskids[t] = (int *) malloc(sizeof(int));
*taskids[t] = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello1, (void *) taskids[t]);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1); }
}
// pthread_join
for(t=0; t<N_THREADS; t++)

{
rc = pthread_join(thread[t], NULL);
if (rc)
7
{
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}

}
pthread_exit(NULL);// ket thuc tien trinh chinh

sum=0;
for(t=0;t<N_THREADS;t++)
{ sum = sum + t;
thread_data_array[t].thread_id = t;
thread_data_array[t].sum = sum;
thread_data_array[t].message = messages[t];

printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello2, (void *)
&thread_data_array[t]);
if (rc)
{ printf("ERROR; return code from pthread_create() is %d\n", rc); exit(-1); }
}
// pthread_join
for(t=0; t<N_THREADS; t++)
{
rc = pthread_join(thread[t], NULL);
if (rc)

{
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}

}

pthread_exit(NULL);// Ket thuc tien trinh chu
}

5.2) Các thread trả kết quả về cho thread chính thông qua pthread_join
int pthread_join( pthread_t inHandle, void
**outputReturnValue);

VD 1: Tạo 3 thread, mỗi thread tính tổng của 10 số ngẫu nhiên.
#include <pthread.h>
8
#include <stdio.h>
#include <stdlib.h>

#define N_THREADS 3// so thread con

void *BusyWork(void *null)
{
int i;
double *result=new double (0.0);// cac bien cuc bo cua tung thread
for (i=0; i<10; i++)
{
*result = *result + (double)rand();
}

//printf("result = %e\n",result);

pthread_exit((void *)result); return NULL;// cach 1

//return (void*)result; //cach 2
}

// chuong trinh chinh se nhan gia tri tra ve trong cach1, cach2 thong qua
//tham so thu 2 cua ham pthread_join

int main (int argc, char *argv[])
{
pthread_t thread[N_THREADS];
pthread_attr_t attr;
int rc, t;
double *sum,*s;

// (1) va (2) dat cac thuoc tinh cua thread
pthread_attr_init(&attr);//(1)
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);//(2)

// Tao nhieu thread
for(t=0; t<N_THREADS; t++)
{
printf("Creating thread %d\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, NULL);
if (rc)
{
printf("ERROR; return code from pthread_create()is %d\n", rc);
exit(-1);

9
}
}

pthread_attr_destroy(&attr);

sum= new double(0.0); // thu thap ket qua


for(t=0; t<N_THREADS; t++)
{
rc = pthread_join(thread[t], (void **)&s);
*sum+=*s;
if (rc)
{
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Completed join with thread =%d and Sum= %10.3f\n",t, *s);
}
printf(" Sum= %10.3f\n",*sum);
pthread_exit(NULL);
}
VD 2: Tạo 10 thread, mỗi thread sẽ tính tổng của 10 số của mảng a[100]

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define array_size 1000
#define N_Thread 10

int a[array_size];
int h=(int) array_size/N_Thread;
void input()
{ int i;
for (i=0;i<array_size; i++)
a[i]=1;
}
void *Worker(void *myThread)// so sanh myThread voi myDataThread
{ int id,i,*tg;
id=*(int *)myThread;
tg=new int;
*tg=0;
for (i=id*h;i<(id+1)*h;i++) { *tg=*tg+a[i]; }
return ((void *)tg);
10
}
void main()
{ pthread_t *threads;
int i; int tasks[N_Thread ];
input();

threads= new pthread_t[N_Thread ];
for (i=0; i<N_Thread ; i++)
{
tasks[i]=i;
if (pthread_create(threads+i,NULL, Worker,&tasks[i]))
{
perror("Error");exit(1);
}
}


int Sum=0;
for (i=0;i<N_Thread ;i++)
{
int *s;
s=new int;
pthread_join(threads[i],(void **)&s);
Sum+=*s;
}
printf("Sum=%d",Sum);

}

5.3) Các thread trả kết quả về cho thread chính thông qua tham biến của
pthread_create

VD: Tính tổng của dãy A gồm n số nguyên với việc sử dụng m thread
(n chia het cho m)
Thuat toan:
Chia deu n ptu cho m thread => moi thread tinh tong cua h=n/m ptu
Đánh so cac thread: 0 => m-1, thì
Thread 0: tinh tong cac ptu tu 0 den h-1
Thread 1: tinh tong cac ptu tu h den 2h-1


=> Goi id chi so cua mot thread nao do => thread phai tinh tong cac ptu tu id*h
den (id+1)h – 1
#include <stdio.h>

×