操作系统实验 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 }
View Code

 

实验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 } 
View Code

 

实验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 }
View Code

 

posted @ 2018-04-17 13:58  LBNOQYX  阅读(966)  评论(0编辑  收藏  举报