Nguyenth Guest
 | Subject: giai lai bai thi lop HCTH062C 28/7/2007, 10:06 | |
| thầy e giải lại bài thi
PHÁT BIểU BÀI TOÁN SX-TT Giả sử có bộ nhớ đệm bao gồm nhiều khoang (items) được tiến trình Producer luôn luôn đưa các sản phẩm P, p,s vào. Tiến trình comsumer luôn luôn lấy sản phẩm ra theo đúng thứ tự. Công việc của Producer phải đồng bộ với comsumer: ko được đưa sản phẩm vào khi buffer đầy, ko được lấy sản phẩm ra khi chưa có.
Sản xuất-Tiêu thụ (đồng bộ bằng 2 đèn hiệu)
#include <stdio.h> #include <conio.h> #include <windows.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE]; char s[BUFFER_SIZE];
int in=0; int out=0;
int nextProduced=1;
HANDLE semEmpty, semFull; // Hai đèn hiệu //semEmpty: đèn hiệu kiểm soát số vùng trống trong bộ đệm //semFull: đèn hiệu kiểm soát số sản phẩm trong bộ đệm
CRITICAL_SECTION critSec; Biến kiểu Mutex ; đèn hiệu nhị phân nội tiến trình
void Producer(void * p){ while (1){ // ... Sản xuất (nextProduced)
// Chờ đến khi có chỗ trống WaitForSingleObject(semEmpty, INFINITE);
EnterCriticalSection(&critSec);
buffer[in]=nextProduced++;
switch ((int)p){ case 1: s[in]=’P’; break; case 2: s[in]=’p’; break; default: s[in]=’S’; };
in=(in+1)%BUFFER_SIZE; // Tăng (semFull) lên 1 ReleaseSemaphore(semFull, 1, NULL);
LeaveCriticalSection(&critSec); SuspendThread(GetCurrentThread()); } } void Consumer(){ int nextConsumed; while (1){ // Chờ đến khi có sản phẩm WaitForSingleObject(semFull, INFINITE);
EnterCriticalSection(&critSec);
nextConsumed=buffer[out]; out=(out+1)%BUFFER_SIZE; // Tăng (semEmpty) lên 1 ReleaseSemaphore (semEmpty, 1, NULL);
LeaveCriticalSection(&critSec);
// ... Tiêu thụ (nextConsumed)
SuspendThread(GetCurrentThread()); } } void ShowBuffer(){ // In nội dung bộ đệm const char * LeftMargin="\n "; int i;
printf(LeftMargin); for(i=0; i<(in*5); i++) putchar(' '); printf("!in");
printf(LeftMargin); for (i=0; i<BUFFER_SIZE-1; i++) printf("%c%2d, ", s[i], buffer[i]); printf("%c%2d", s[BUFFER_SIZE-1], buffer[BUFFER_SIZE-1]);
printf(LeftMargin); for(i=0; i<(out*5); i++) putchar(' '); printf("^out");
printf("\n"); } int main(){ HANDLE ProducerHandle1, ProducerHandle2; HANDLE ConsumerHandle1, ConsumerHandle2;
DWORD ProducerID1, ProducerID2; DWORD ConsumerID1, ConsumerID2;
semEmpty=CreateSemaphore(0, BUFFER_SIZE, BUFFER_SIZE, 0); semFull=CreateSemaphore(0, 0, BUFFER_SIZE, 0);
InitializeCriticalSection(&critSec);
// Tạo các luồng nhưng ở trạng thái ngủ (Suspend) ProducerHandle1=CreateThread(0,0, (LPTHREAD_START_ROUTINE)Producer, (void *) 1, 4, &ProducerID1); ProducerHandle2=CreateThread(0,0, (LPTHREAD_START_ROUTINE)Producer, (void *) 2, 4, &ProducerID2);
ConsumerHandle1=CreateThread(0,0, (LPTHREAD_START_ROUTINE)Consumer, 0, 4, &ConsumerID1); ConsumerHandle2=CreateThread(0,0, (LPTHREAD_START_ROUTINE)Consumer, 0, 4, &ConsumerID2); while(1) { printf("\n- Nhấn P/p để sản xuất, C/c để tiêu thụ:"); switch (getch()){ case 'P': // Đánh thức luồng SX 1 ResumeThread(ProducerHandle1); break; case 'p': // Đánh thức luồng SX 2 ResumeThread(ProducerHandle2); break; case 'C': // Đánh thức luồng TT 1 ResumeThread(ConsumerHandle1); break; case 'c': // Đánh thức luồng TT 2 ResumeThread(ConsumerHandle2); break; case '0': // Kết thúc ứng dụng printf("\n"); CloseHandle(semEmpty); CloseHandle(semFull); DeleteCriticalSection(&critSec); return 0; } EnterCriticalSection(&critSec); ShowBuffer(); LeaveCriticalSection(&critSec); } }
ghi chú
(theo dinh nhĩa)typedef int semaphore; semaphore s = n; (thực thi trong C)HANDLE s; s=CreateSemaphore (0, n, max, t); // t -tên đèn hiệu hoặc 0 // nếu t là 1 chuỗi ký tự trong ngoặc kép(" ") thì đó là tên ấn định cho đèn hiệu liên tiến trình(liên lạc được tiến trình khác ) . Nếu dùng 0 thay cho t; null thi đèn hiệu mới tạo chỉ có nội tiến trình (hiệu quả hơn nhanh hơn)
(thực thi trong C)wait (s); (thực thi trong C)WaitForSingleObject (s, timeout); /* timeout = INFINITE hoặc số mili giây chờ*/
(thực thi trong C)signal (s); (thực thi trong C)ReleaseSemaphore (s, 1, NULL); |
|