操作系统实验 windows编程多线程 生产者消费者问题 画圆画方(内置bug版)
实验3:随便写的
1 #include <windows.h> 2 #include <string> 3 #include <stdio.h> 4 #pragma warning(disable:4996) 5 6 CRITICAL_SECTION cs; 7 8 int cnt; 9 10 DWORD WINAPI Thread( LPVOID lpParam ) 11 { 12 int n = (int)lpParam; 13 14 if ( n == 1 ) 15 for ( int i = 1; i <= 1000; i++ ) 16 { 17 EnterCriticalSection(&cs); 18 printf( "第%d个线程输出%d\n", n, i ); 19 LeaveCriticalSection(&cs); 20 Sleep(500); 21 } 22 if ( n == 2 ) 23 for ( int i = 1000; i >= 1; i-- ) 24 { 25 EnterCriticalSection(&cs); 26 printf( "第%d个线程输出%d\n", n, i ); 27 LeaveCriticalSection(&cs); 28 Sleep(500); 29 } 30 31 return 0; 32 } 33 34 int main() 35 { 36 cnt = 0; 37 38 DWORD ThreadID; 39 HANDLE hThread[2]; 40 InitializeCriticalSection(&cs); 41 for ( int i = 0; i < 2; i++ ) 42 { 43 hThread[i] = CreateThread( NULL, 0, Thread, (LPVOID)(i+1), 0, &ThreadID ); 44 printf( "Thread %d has been created\n", i ); 45 } 46 WaitForMultipleObjects( 2, hThread, TRUE, INFINITE ); 47 48 DeleteCriticalSection(&cs); 49 return 0; 50 }
实验4:https://blog.csdn.net/morewindows/article/details/7577591
修改了部分代码并添加了注释
1 #include <stdio.h> 2 #include <process.h> 3 #include <windows.h> 4 5 const int THREADNUM = 4; 6 const int END_PRODUCE_NUMBER = 9; //要生产的产品个数 7 const int BUFFER_SIZE = 4; //缓冲区个数 8 int g_Buffer[BUFFER_SIZE]; //缓冲池 9 int g_i, g_j; //信号量与关键段 10 11 CRITICAL_SECTION g_cs; 12 HANDLE g_hSemaphoreBufferEmpty, g_hSemaphoreBufferFull; 13 14 int data=0; 15 16 //生产者线程函数 17 unsigned int __stdcall ProducerThreadFun(PVOID pM) 18 { 19 while( data < END_PRODUCE_NUMBER ) 20 { 21 //等待有空的缓冲区出现 22 WaitForSingleObject( g_hSemaphoreBufferEmpty, INFINITE ); 23 24 //互斥的访问缓冲区 25 EnterCriticalSection(&g_cs); 26 27 //如果投放了足够多的数据,就直接离开临界区 28 if( data == END_PRODUCE_NUMBER ) 29 { 30 LeaveCriticalSection(&g_cs); 31 break; 32 } 33 34 //否则投放数据 35 data++; 36 g_Buffer[g_i] = data; 37 38 39 printf("%d号生产者在缓冲池中第%d个缓冲区中投放数据%d\n\n", GetCurrentThreadId(), g_i, g_Buffer[g_i]); 40 41 //循环投放数据 42 g_i = ( g_i + 1 ) % BUFFER_SIZE; 43 LeaveCriticalSection(&g_cs); 44 45 Sleep(50); 46 47 //将Full信号量+1,表示生产了一个数据可以取了 48 ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL); 49 } 50 51 printf("生产者完成任务,线程结束运行\n\n"); 52 return 0; 53 } 54 55 //消费者线程函数 56 unsigned int __stdcall ConsumerThreadFun(PVOID pM) 57 { 58 while (true) 59 { 60 //等待非空的缓冲区出现 61 WaitForSingleObject( g_hSemaphoreBufferFull, INFINITE ); 62 63 //互斥的访问缓冲区 64 EnterCriticalSection(&g_cs); 65 66 printf("%d号消费者从缓冲池第%d个缓冲区取出数据%d\n\n",GetCurrentThreadId(), g_j, g_Buffer[g_j]); 67 68 69 if ( g_Buffer[g_j] == END_PRODUCE_NUMBER ) 70 { 71 LeaveCriticalSection(&g_cs); 72 break; 73 } 74 75 g_j = ( g_j + 1 ) % BUFFER_SIZE; 76 LeaveCriticalSection(&g_cs); 77 78 Sleep(50); 79 80 //释放一个数据使empty信号量+1,表示多了一个空位可以生产了 81 ReleaseSemaphore(g_hSemaphoreBufferEmpty, 1, NULL); 82 } 83 84 printf("%d号消费者收到通知,线程结束运行\n\n", GetCurrentThreadId()); 85 86 return 0; 87 } 88 89 int main() 90 { 91 printf(" 生产者消费者问题 3生产者 1消费者 4缓冲区\n\n"); 92 93 //初始化临界区 94 InitializeCriticalSection(&g_cs); 95 96 //初始化信号量,一个记录有产品的缓冲区个数,另一个记录空缓冲区个数. 97 g_hSemaphoreBufferEmpty = CreateSemaphore(NULL, 4, 4, NULL); //开始信号量为4个,代表可以生产4个数据 98 g_hSemaphoreBufferFull = CreateSemaphore(NULL, 0, 4, NULL); //开始信号量为0个,代表可以取走0个数据 99 g_i = 0; 100 g_j = 0; 101 memset( g_Buffer, 0, sizeof(g_Buffer) ); 102 103 HANDLE hThread[THREADNUM]; 104 //生产者线程 3个 105 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); 106 hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); 107 hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL); 108 //消费者线程 1个 109 hThread[3] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun, NULL, 0, NULL); 110 111 112 //等待线程全部结束后关闭信号量 113 WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE); 114 for (int i = 0; i < THREADNUM; i++) 115 CloseHandle(hThread[i]); 116 117 //销毁信号量和关键段 118 CloseHandle(g_hSemaphoreBufferEmpty); 119 CloseHandle(g_hSemaphoreBufferFull); 120 DeleteCriticalSection(&g_cs); 121 return 0; 122 }
实验5:写的崩溃,内置一神秘bug,绘制点数如果太多比如超过500绘制一段时间就会未响应,而且绘制期间鼠标变成小圆圈
猜测是消息循环的问题,因为这是综合了多家代码并进行大量经验主义的修修补补才写成的(实际上完全不懂自己写的是什么)求大神解答为什么会有这种bug
1 #include <windows.h> 2 #include <math.h> 3 #define PI 3.14159265 4 #define POINTNUM 400 5 6 CRITICAL_SECTION cs; 7 static TCHAR szAppName[] = TEXT("画圆画方bug版"); 8 static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 9 10 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) 11 { 12 HWND hWnd; 13 MSG msg; 14 WNDCLASS wndclass; 15 16 wndclass.style = CS_HREDRAW | CS_VREDRAW; 17 wndclass.lpfnWndProc = WndProc; 18 wndclass.cbClsExtra = 0; 19 wndclass.cbWndExtra = 0; 20 wndclass.hInstance = hInstance; 21 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 22 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 23 wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); 24 wndclass.lpszMenuName = NULL; 25 wndclass.lpszClassName = szAppName; 26 27 if (!RegisterClass(&wndclass)) 28 { 29 MessageBox (NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); 30 return 0; 31 } 32 33 hWnd = CreateWindow(szAppName, // window class name 34 szAppName, // window caption 35 WS_OVERLAPPEDWINDOW, // window style 36 CW_USEDEFAULT, // initial x position 37 CW_USEDEFAULT, // initial y position 38 800, // initial x size 39 600, // initial y size 40 NULL, // parent window handle 41 NULL, // window menu handle 42 hInstance, // program instance handle 43 NULL); // creation parameters 44 45 ShowWindow(hWnd, iCmdShow); 46 UpdateWindow(hWnd); 47 48 while (GetMessage(&msg, NULL, 0, 0)) 49 { 50 TranslateMessage(&msg); 51 DispatchMessage(&msg); 52 } 53 54 return msg.wParam; 55 } 56 57 DWORD WINAPI DrawCircle( LPVOID lpParama ) 58 { 59 HDC hDC = HDC(lpParama); 60 int x = 200, y = 250, r = 50; 61 COLORREF color = RGB(255,0,0); 62 63 int xr, yr; 64 for (int i=0; i <= POINTNUM; i++) 65 { 66 EnterCriticalSection(&cs); 67 68 double rec = ((double)i/POINTNUM*360)*PI/180; 69 xr = r*cos(rec); 70 yr = r*sin(rec); 71 72 SetPixel( hDC, x+xr, y+yr, color ); 73 74 LeaveCriticalSection(&cs); 75 Sleep(10); 76 } 77 return 0; 78 } 79 80 DWORD WINAPI DrawRect( LPVOID lpParama ) 81 { 82 HDC hDC = HDC(lpParama); 83 84 int halfl = 50, halfh =30; 85 int x = 250, y = 125; 86 COLORREF color = RGB(255,0,0); 87 88 int average = POINTNUM/4; 89 90 int xr, yr; 91 int adx, ady; 92 93 xr = x - halfl; yr = y - halfh; 94 ady = 0; 95 for ( int i = 0; i <= average; i++ ) 96 { 97 EnterCriticalSection(&cs); 98 99 adx = (2*halfl)*i/average; 100 SetPixel( hDC, x+xr+adx, y+yr+ady, color ); 101 102 LeaveCriticalSection(&cs); 103 Sleep(10); 104 } 105 106 Sleep(10); 107 xr = x + halfl; yr = y - halfh; 108 adx = 0; 109 for ( int i = 0; i <= average; i++ ) 110 { 111 EnterCriticalSection(&cs); 112 113 ady = (2*halfh)*i/average; 114 SetPixel( hDC, x+xr+adx, y+yr+ady, color ); 115 116 LeaveCriticalSection(&cs); 117 Sleep(10); 118 } 119 120 Sleep(10); 121 xr = x + halfl; yr = y + halfh; 122 ady = 0; 123 for ( int i = 0; i <= average; i++ ) 124 { 125 EnterCriticalSection(&cs); 126 127 adx = -(2*halfl)*i/average; 128 SetPixel( hDC, x+xr+adx, y+yr+ady, color ); 129 130 LeaveCriticalSection(&cs); 131 Sleep(10); 132 } 133 134 Sleep(10); 135 xr = x -halfl; yr = y + halfh; 136 adx = 0; 137 for ( int i = 0; i <= average; i++ ) 138 { 139 EnterCriticalSection(&cs); 140 141 ady = -(2*halfh)*i/average; 142 SetPixel( hDC, x+xr+adx, y+yr+ady, color ); 143 144 LeaveCriticalSection(&cs); 145 Sleep(10); 146 } 147 return 0; 148 } 149 150 151 static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 152 { 153 HDC hDC; 154 PAINTSTRUCT ps; 155 156 switch (message) 157 { 158 case WM_CREATE: 159 return 0; 160 161 case WM_PAINT: 162 { 163 hDC = BeginPaint(hWnd, &ps); 164 165 DWORD ThreadID; 166 HANDLE hThread[2]; 167 InitializeCriticalSection(&cs); 168 169 hThread[0] = CreateThread( NULL, 0, DrawCircle, (LPVOID)(hDC), 0, &ThreadID ); 170 hThread[1] = CreateThread( NULL, 0, DrawRect, (LPVOID)(hDC), 0, &ThreadID ); 171 172 WaitForMultipleObjects( 2, hThread, TRUE, INFINITE ); 173 DeleteCriticalSection(&cs); 174 175 TextOut(hDC, 300, 400, TEXT("绘制完毕!"), 11); 176 } 177 EndPaint(hWnd, &ps); 178 return 0; 179 180 case WM_DESTROY: 181 PostQuitMessage(0); 182 return 0 ; 183 } 184 185 return DefWindowProc (hWnd, message, wParam, lParam); 186 }
什么时候能够不再这么懒惰