1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng Lập trình mạng: Chương 3 - Lê Bá Vui

20 8 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Bài giảng Lập trình mạng: Chương 3 Giới thiệu lập trình đa luồng, cung cấp cho người học những kiến thức như: Khởi tạo và thực thi các luồng trên Windows; Đồng bộ và tránh xung đột trong lập trình đa luồng. Mời các bạn cùng tham khảo!

Chương Giới thiệu lập trình đa luồng Chương Giới thiệu lập trình đa luồng 3.1 Khởi tạo thực thi luồng Windows 3.2 Đồng tránh xung đột lập trình đa luồng 114 3.1 Khởi tạo thực thi luồng Khởi tạo luồng mới: HANDLE CreateThread( LPSECURITY_ATTRIBUTES ThreadAttributes, DWORD StackSize, LPTHREAD_START_ROUTINE StartAddress, LPVOID Parameter, DWORD CreationFlags, LPDWORD ThreadId ); Các tham số cần quan tâm: • StartAddress tên hàm thực thi, cần khai báo trước • Parameter trỏ tham số truyền vào hàm thực thi Kết trả về: • FALSE – xảy lỗi, dùng hàm GetLastError() để xác định • NOT FALSE – HANDLE sử dụng để tham chiếu đến luồng 115 3.1 Khởi tạo thực thi luồng Khởi tạo luồng mới: • Hàm CreateThread() yêu cầu khai báo hàm thực thi (có thể khai báo prototype trước thực nội dung hàm) • Hàm thực thi chạy sau luồng tạo • Ví dụ khai báo prototype hàm thực thi: DWORD WINAPI MyThreadStart(LPVOID p); 116 3.1 Khởi tạo thực thi luồng Xóa luồng: • Mục đích giải phóng tài ngun (bộ nhớ) sau luồng thực xong • Nếu tạo nhiều luồng mà khơng giải phóng tài ngun: – Gây rị rỉ nhớ – Khơng tạo thêm luồng • Khi chương trình kết thúc, luồng tự động giải phóng BOOL CloseHandle(HANDLE hObject); 117 3.1 Khởi tạo thực thi luồng Ví dụ: #include #include DWORD WINAPI helloFunc(LPVOID arg ) { printf(“Hello Thread\n”); return 0; } main() { HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); } Kết thực chương trình? 118 3.1 Khởi tạo thực thi luồng Ví dụ: Một hai khả xảy ra: • Dịng chữ “Hello Thread” in hình • Dịng chữ khơng in hình => Do chương trình kết thúc trước hàm thực thi chạy => Cần có chế chờ cho luồng chạy xong 119 3.1 Khởi tạo thực thi luồng Ví dụ: #include #include BOOL threadDone = FALSE ; DWORD WINAPI helloFunc(LPVOID arg ) { printf(“Hello Thread\n”); threadDone = TRUE ; return 0; } main() { HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); while (!threadDone); } Vấn đề với đoạn chương trình? 120 3.1 Khởi tạo thực thi luồng Cơ chế đợi luồng thực thi: Sử dụng hàm WaitForSingleObject() để đợi luồng thực thi xong DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); Luồng gọi hàm dừng đợi khi: • Hết sau dwMilliseconds giây • Luồng thực thi xong Nếu muốn chờ hàm thực thi xong truyền INFINITE cho tham số dwMilliseconds 121 3.1 Khởi tạo thực thi luồng Ví dụ: #include #include BOOL threadDone = FALSE; DWORD WINAPI helloFunc(LPVOID arg) { printf(“Hello Thread\n”); threadDone = TRUE; return 0; } main() { HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); WaitForSingleObject(hThread, INFINITE); } 122 3.1 Khởi tạo thực thi luồng Cơ chế đợi luồng thực thi: Sử dụng hàm WaitForMultipleObject() để đợi nhiều luồng thực thi xong (tối đa 64 luồng) DWORD WaitForMultipleObjects( DWORD nCount, CONST HANDLE *lpHandles, // array BOOL fWaitAll, // wait for one or all DWORD dwMilliseconds); nCount số phần tử mảng lpHandles fWaitAll = TRUE => hàm trả kết tất luồng thực xong fWaitAll = FALSE => hàm trả kết luồng thực xong, giá trị trả số luồng mảng 123 3.1 Khởi tạo thực thi luồng Ví dụ: #include #include const int numThreads = 4; DWORD WINAPI helloFunc(LPVOID arg) { printf(“Hello Thread\n”); return 0; } main() { HANDLE hThread[numThreads]; for (int i = 0; i < numThreads; i++) hThread[i] = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL); WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); } 124 3.1 Khởi tạo thực thi luồng Ví dụ: cập nhật đoạn chương trình để hiển thị thông điệp ứng với luồng tạo Hello from Thread #0 Hello from Thread #1 Hello from Thread #2 Hello from Thread #3 125 3.1 Khởi tạo thực thi luồng Ví dụ: cập nhật đoạn chương trình để hiển thị thơng điệp ứng với luồng tạo DWORD WINAPI threadFunc(LPVOID pArg) { int* p = (int*)pArg; int myNum = *p; printf(“Thread number %d\n”, myNum); } // from main(): for (int i = 0; i < numThreads; i++) { hThread[i] = CreateThread(NULL, 0, threadFunc, &i, 0, NULL); } 126 3.2 Đồng tránh xung đột lập trình đa luồng • Việc truy nhập đồng thời vào biến từ nhiều luồng dẫn đến xung đột – Xung đột đọc/ghi liệu – Xung đột ghi/ghi liệu • Lỗi phổ biến lập trình đa luồng • Có thể khơng rõ ràng tất tình => Khó gỡ lỗi 127 3.2 Đồng tránh xung đột lập trình đa luồng • Các phương pháp tránh xung đột – Hạn chế sử dụng biến toàn cục, nên sử dụng biến cục khai báo hàm thực thi luồng – Quản lý việc truy nhập tài nguyên dùng chung • Mutex • Critical Section • Events • Semaphores 128 3.2 Đồng tránh xung đột lập trình đa luồng • Sử dụng Critical Section – Là chế đơn giản, sử dụng nhiều – Tạo đối tượng mới: CRITICAL_SECTION cs; – Khởi tạo hủy đối tượng InitializeCriticalSection(&cs); DeleteCriticalSection(&cs); 129 3.2 Đồng tránh xung đột lập trình đa luồng • Sử dụng Critical Section – Truy nhập vào vùng tranh chấp: EnterCriticalSection(&cs); • Hàm tạm dừng luồng luồng khác vùng tranh chấp • Hàm trả khơng có luồng vùng tranh chấp – Rời khỏi vùng tranh chấp: LeaveCriticalSection(&cs); 130 3.2 Đồng tránh xung đột lập trình đa luồng • Sử dụng Critical Section #define NUMTHREADS CRITICAL_SECTION g_cs; // why does this have to be global? int g_sum = 0; DWORD WINAPI threadFunc(LPVOID arg) { int mySum = bigComputation(); EnterCriticalSection(&g_cs); g_sum += mySum; // threads access one at a time LeaveCriticalSection(&g_cs); return 0; } main() { HANDLE hThread[NUMTHREADS]; InitializeCriticalSection(&g_cs); for (int i = 0; i < NUMTHREADS; i++) hThread[i] = CreateThread(NULL, 0, threadFunc, NULL, 0, NULL); WaitForMultipleObjects(NUMTHREADS, hThread, TRUE, INFINITE); DeleteCriticalSection(&g_cs); } 131 3.2 Đồng tránh xung đột lập trình đa luồng Bài tập static long num_steps = 100000; double step, pi; void main() { int i; double x, sum = 0.0; Đoạn chương trình sử dụng để tính xấp xỉ số PI Viết lại chương trình sử dụng multi-thread step = 1.0 / (double)num_steps; for (i = 0; i < num_steps; i++) { x = (i + 0.5) * step; sum = sum + 4.0 / (1.0 + x * x); } pi = step * sum; printf("Pi = % f\n", pi); } 132 .. .Chương Giới thiệu lập trình đa luồng 3. 1 Khởi tạo thực thi luồng Windows 3. 2 Đồng tránh xung đột lập trình đa luồng 114 3. 1 Khởi tạo thực thi luồng Khởi tạo... DeleteCriticalSection(&g_cs); } 131 3. 2 Đồng tránh xung đột lập trình đa luồng Bài tập static long num_steps = 100000; double step, pi; void main() { int i; double x, sum = 0.0; Đoạn chương trình sử dụng để... } 126 3. 2 Đồng tránh xung đột lập trình đa luồng • Việc truy nhập đồng thời vào biến từ nhiều luồng dẫn đến xung đột – Xung đột đọc/ghi liệu – Xung đột ghi/ghi liệu • Lỗi phổ biến lập trình đa

Ngày đăng: 04/11/2022, 09:35

Xem thêm: