win32线程创建、线程同步以及读者写者问题

来源:互联网 发布:java checkboxgroup 编辑:程序博客网 时间:2024/05/17 01:58
include "stdafx.h" #include <stdio.h>  #include <windows.h>  #include <process.h>//设置控制台输出颜色  BOOL SetConsoleColor(WORD wAttributes)  {  HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);  if (hConsole == INVALID_HANDLE_VALUE)  return FALSE;  return SetConsoleTextAttribute(hConsole, wAttributes);  }//设置控制台输出蓝色字体void ConsolePrintBlue(char *pszFormat, ...)  {  va_list   pArgList;  va_start(pArgList, pszFormat);  SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN);vfprintf(stdout, pszFormat, pArgList); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); va_end(pArgList);  }//线程函数unsigned int __stdcall Threadfun(LPVOID lpParam)  {  LPDWORD pData = (LPDWORD)lpParam;for(int i = 0;i < 10; i++)  {  Sleep(100);  //子线程挂起100毫秒printf("Thread_ID = %d , \tParameters = %d, \ti = %d\n", GetCurrentThreadId(), *pData, i);  }  _endthreadex(0);  return 0;  }  //如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread()void ThreadexTest(){ConsolePrintBlue("--------- 进入线程创建、挂起、关闭测试 ---------\n");DWORD Para0, Para1;  // 设置线程传递参数HANDLE hThread[2];  Para0 = 0; Para1 = 1;   //创建线程0并挂起hThread[0] = (HANDLE)_beginthreadex(NULL, 0, Threadfun, &Para0, CREATE_SUSPENDED, NULL);  hThread[1] = (HANDLE)_beginthreadex(NULL, 0, Threadfun, &Para1, 0, NULL);  Sleep(110);  //主线程挂起110毫秒,期间线程1正好可以输出一次ResumeThread(hThread[0]);    //恢复线程0SuspendThread(hThread[1]);   //挂起线程1Sleep(510); //主线程挂起510毫秒,期间线程0正好可以输出5次//终止线程0的运行TerminateThread(hThread[0], 0);  //并不保证线程被终止,最好采用线程函数返回方式终止ResumeThread(hThread[1]);        //恢复线程1WaitForSingleObject(hThread[1], INFINITE);   //等待线程1执行完CloseHandle(hThread[0]);CloseHandle(hThread[1]);ConsolePrintBlue("--------- 结束线程创建、挂起、关闭测试 ---------\n\n\n");}CRITICAL_SECTION g_cs;//关键段线程函数unsigned int _stdcall  CriticalSection(LPVOID lpParam){ EnterCriticalSection(&g_cs);//进入关键段printf("Thread_ID%d start\n", GetCurrentThreadId());ConsolePrintBlue("挂起线程100毫秒\n");Sleep(100);  //挂起线程100毫秒printf("Thread_ID%d end\n\n", GetCurrentThreadId());LeaveCriticalSection(&g_cs);//离开关键段_endthreadex(0);return 0;}//关键段测试函数void CriticalSectionTest(){ConsolePrintBlue("\n--------- 使用临界区(CRITICAL_SECTION及其系列函数)实现线程同步 ---------\n");InitializeCriticalSection(&g_cs);    //初始化g_cs的成员 HANDLE hThread[10]; for(int i = 0; i < 10; i++){ hThread[i] = (HANDLE)_beginthreadex(NULL, 0, CriticalSection, NULL, 0, NULL);  }WaitForMultipleObjects(10, hThread, TRUE, INFINITE);   for(int i = 0; i < 10; i++){CloseHandle(hThread[i]);} DeleteCriticalSection(&g_cs);//删除关键段ConsolePrintBlue("\\----- end ------\n\n\n");}RTL_SRWLOCK  lock;//互斥锁线程函数unsigned int _stdcall  SrwLock(LPVOID lpParam){ AcquireSRWLockExclusive(&lock);  //进入读写锁printf("Thread_ID%d start\n", GetCurrentThreadId());ConsolePrintBlue("挂起线程100毫秒\n");Sleep(100);  //挂起线程100毫秒printf("Thread_ID%d end\n\n", GetCurrentThreadId());ReleaseSRWLockExclusive(&lock);  //结束读写锁_endthreadex(0);return 0;}//互斥锁测试函数void SrwLockTest(){ConsolePrintBlue("\n--------- 使用互斥锁(RTL_SRWLOCK及其系列函数)实现线程同步 ---------\n");HANDLE hThread[10]; InitializeSRWLock(&lock);//初始化lock的成员 for(int i = 0; i < 10; i++){ hThread[i] = (HANDLE)_beginthreadex(NULL, 0, SrwLock, NULL, 0, NULL);  }WaitForMultipleObjects(10, hThread, TRUE, INFINITE);   ConsolePrintBlue("\\----- end ------\n\n\n");}HANDLE semaphore;//信号量线程函数unsigned int _stdcall  Semaphore(LPVOID lpParam){WaitForSingleObject(semaphore, INFINITE);  //执行WaitForSingleObject一次,计数值就减一 printf("Thread_ID%d start\n", GetCurrentThreadId());ConsolePrintBlue("挂起线程100毫秒\n");Sleep(100);printf("Thread_ID%d end\n\n", GetCurrentThreadId());ReleaseSemaphore(semaphore, 1, NULL);    //计数加一_endthreadex(0);return 0;}//信号量测试函数void SemaphoreTest(){ConsolePrintBlue("\n--------- 使用信号量内核对象实现线程同步 ---------\n");HANDLE hThread[10];semaphore = CreateSemaphore(NULL, 1, 1, NULL);  //初始计数为1,最大计数为1for(int i = 0; i < 10; i++){ hThread[i] = (HANDLE)_beginthreadex(NULL, 0, Semaphore, NULL, 0, NULL);  }WaitForMultipleObjects(10, hThread, TRUE, INFINITE);   CloseHandle(semaphore);ConsolePrintBlue("\\----- end ------\n\n\n");}HANDLE hEvent; //事件线程函数unsigned int _stdcall  Event(LPVOID lpParam){WaitForSingleObject(hEvent, INFINITE);  //自动复位,变为无信号printf("Thread_ID%d start\n", GetCurrentThreadId());ConsolePrintBlue("挂起线程100毫秒\n");Sleep(100);printf("Thread_ID%d end\n\n", GetCurrentThreadId());SetEvent(hEvent);    //设置为有信号_endthreadex(0);return 1;}//事件测试函数void EventTest(){ConsolePrintBlue("\n--------- 使用事件内核对象实现线程同步 ---------\n");HANDLE hThread[10];hEvent = CreateEvent(NULL, false, true, NULL); //初始bManualReset设置为false,bInitialState设置为有信号for(int i = 0; i < 10;i++){hThread[i] =(HANDLE)_beginthreadex(NULL, 0, Event , NULL, 0, NULL);  }WaitForMultipleObjects(10, hThread, TRUE, INFINITE);   CloseHandle(hEvent);ConsolePrintBlue("\\----- end ------\n\n\n");}const int QUEUE_LEN = 10;  //环形队列长度int g_queue[QUEUE_LEN];    //环形队列int g_i, g_j;                int nDataR, nDataW;       HANDLE g_hEmpty, g_hFull;    //读写信号量,读者在读信号量不为空则可读,写者在写信息量不为满则可写 HANDLE g_hEventReader, g_hEventWriter;  //读者、写者事件,仅能一次一个写者进行写操作,一个读者进行读操作//读者线程输出函数void ReaderPrintRed(char *pszFormat, ...)  {  va_list   pArgList;  va_start(pArgList, pszFormat);  EnterCriticalSection(&g_cs);  SetConsoleColor(FOREGROUND_RED);vfprintf(stdout, pszFormat, pArgList); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); LeaveCriticalSection(&g_cs);  va_end(pArgList);  }  //写者线程输出函数  void WriterPrintGreen(char *pszStr, ...)  {  va_list pArgList;  va_start(pArgList, pszStr); EnterCriticalSection(&g_cs);  SetConsoleColor(FOREGROUND_GREEN);   vfprintf(stdout, pszStr, pArgList); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);  LeaveCriticalSection(&g_cs);  }   //单个读者线程函数unsigned int __stdcall ReaderThreadFun(PVOID pM)  {  ReaderPrintRed("编号为%d的读者开始读取数据...\n", GetCurrentThreadId());  int nDataR = 0;  while (nDataR < 20)  {  WaitForSingleObject(g_hFull, INFINITE);  //等待数据队列不为空 nDataR = g_queue[g_i];  g_i = (g_i + 1)%QUEUE_LEN;  ReaderPrintRed("编号为%d读者从队列中读取数据%d\n", GetCurrentThreadId(), nDataR);  ReleaseSemaphore(g_hEmpty, 1, NULL);  } ReaderPrintRed("编号为%d的读者结束读取数据//end\n", GetCurrentThreadId());  return 0;  }//单个写者线程函数unsigned int __stdcall WriterThreadFun(PVOID pM)  {  WriterPrintGreen("编号为%d的写者开始写数据...\n", GetCurrentThreadId());int nDataR = 0;  while (nDataR < 20)  {  WaitForSingleObject(g_hEmpty, INFINITE);   //等待数据队列有空位g_queue[g_j] = ++nDataR;  g_j = (g_j + 1)%QUEUE_LEN;  WriterPrintGreen("编号为%d写者将数据%d写入队列\n", GetCurrentThreadId(), nDataR); ReleaseSemaphore(g_hFull, 1, NULL);       //g_hFull信号量加一} WriterPrintGreen("编号为%d的写者结束写数据//end\n", GetCurrentThreadId());  return 0;  } //多个读者线程函数unsigned int __stdcall MultiReaderThreadFun(PVOID pM){ReaderPrintRed("编号为%d的读者开始读取数据...\n", GetCurrentThreadId());  while (nDataR < 20)  {  WaitForSingleObject(g_hEventReader, INFINITE);  //一次只能进入一个读者if (nDataR >= 20)  {SetEvent(g_hEventReader);ReaderPrintRed("编号为%d的读者结束读数据..//end\n", GetCurrentThreadId());  return 0;}WaitForSingleObject(g_hFull, INFINITE);nDataR = g_queue[g_i];  g_i = (g_i + 1)%QUEUE_LEN;  ReaderPrintRed("编号为%d读者从队列中读取数据%d\n", GetCurrentThreadId(), nDataR);ReleaseSemaphore(g_hEmpty, 1, NULL);SetEvent(g_hEventReader);}  ReaderPrintRed("编号为%d的读者结束读取数据//end\n", GetCurrentThreadId());  return 0;  }//多个写者线程函数unsigned int __stdcall MultiWriterThreadFun(PVOID pM){   WriterPrintGreen("编号为%d的写者开始写数据...\n", GetCurrentThreadId());while (nDataW < 20)  {  WaitForSingleObject(g_hEventWriter, INFINITE);  //一次仅能进入一个读者if (nDataW >= 20){SetEvent(g_hEventWriter);WriterPrintGreen("编号为%d的写者结束写数据..//end\n", GetCurrentThreadId());  return 0;}WaitForSingleObject(g_hEmpty, INFINITE);g_queue[g_j] = ++nDataW;  g_j = (g_j + 1) % QUEUE_LEN;  WriterPrintGreen("编号为%d的写者将数据%d写入队列\n", GetCurrentThreadId(), nDataW);  ReleaseSemaphore(g_hFull, 1, NULL); SetEvent(g_hEventWriter);}  WriterPrintGreen("编号为%d的写者结束写数据//end\n", GetCurrentThreadId());  return 0;  }//一个写者一个读者void SingleReaderSingleWirterTest(){  ConsolePrintBlue("\n----------- 模拟一个写者和一个读者之间访问环形队列操作 ---------\n");HANDLE hThread[2]; g_i = g_j = 0; nDataR = nDataW = 0;InitializeCriticalSection(&g_cs);    //初始化g_cs的成员 g_hEmpty = CreateSemaphore(NULL, QUEUE_LEN, QUEUE_LEN, NULL);  //初始信号量为满,最大信号量为环形队列总个数 g_hFull = CreateSemaphore(NULL, 0, QUEUE_LEN, NULL);   //初始信号量为空,最大信号量为环形队列总个数  hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ReaderThreadFun, NULL, 0, NULL);  hThread[1] = (HANDLE)_beginthreadex(NULL, 0, WriterThreadFun, NULL, 0, NULL);  WaitForMultipleObjects(2, hThread, TRUE, INFINITE);  for (int i = 0; i < 2; i++)  {CloseHandle(hThread[i]); }CloseHandle(g_hEmpty);  CloseHandle(g_hFull);  ConsolePrintBlue("循环队列中保存的数为:\n");for (int i = 0; i < QUEUE_LEN; i++){printf("%-6d", g_queue[i]);}printf("\n");DeleteCriticalSection(&g_cs);//删除关键段ConsolePrintBlue("\\----- end ------\n\n\n");}//一个写者十个读者void MultiReaderSingleWirterTest(){ConsolePrintBlue("\n----------- 模拟一个写者和多个读者之间访问缓形队列操作 ---------\n");g_i = g_j = 0;  HANDLE hThreadR[10];HANDLE hThreadW;nDataR = nDataW = 0;InitializeCriticalSection(&g_cs);  g_hEmpty = CreateSemaphore(NULL, 1, QUEUE_LEN, NULL);  g_hFull = CreateSemaphore(NULL, 0, QUEUE_LEN, NULL);  g_hEventReader = CreateEvent(NULL, false, true, NULL);        //设置事件,每次仅能一个读者读for (int i = 0; i < 10; i++){hThreadR[i] = (HANDLE)_beginthreadex(NULL, 0, MultiReaderThreadFun, NULL, 0, NULL); } hThreadW = (HANDLE)_beginthreadex(NULL, 0, WriterThreadFun, NULL, 0, NULL);  WaitForSingleObject(hThreadW, INFINITE);WaitForMultipleObjects(10, hThreadR, TRUE, INFINITE);  for (int i = 0; i < 10; i++)  {CloseHandle(hThreadR[i]); }CloseHandle(hThreadW);CloseHandle(g_hEmpty);  CloseHandle(g_hFull);  ConsolePrintBlue("循环队列中保存的数为:\n");for (int i = 0; i < QUEUE_LEN; i++){printf("%-6d", g_queue[i]);}printf("\n");DeleteCriticalSection(&g_cs);  ConsolePrintBlue("\\----- end ------\n\n\n");}//十个写者十个读者void MultiReaderMultiReaderWriterTest() {ConsolePrintBlue("\n----------- 模拟多个写者和多个读者之间访问环形队列操作 ---------\n");g_i = g_j = 0;  HANDLE hThreadR[10];HANDLE hThreadW[10];nDataR = nDataW = 0;InitializeCriticalSection(&g_cs);   g_hEventReader = CreateEvent(NULL, false, true, NULL);        //设置事件,每次仅能一个读者读g_hEventWriter = CreateEvent(NULL, false, true, NULL);        //设置事件,每次仅能一个写者写g_hEmpty = CreateSemaphore(NULL, 1, QUEUE_LEN, NULL);         //初始计数为一,最大计数为十g_hFull = CreateSemaphore(NULL, 0, QUEUE_LEN, NULL);          //初始计数为零,最大计数为十for (int i = 0; i < 10; i++){hThreadR[i] = (HANDLE)_beginthreadex(NULL, 0, MultiReaderThreadFun, NULL, 0, NULL); } for(int i = 0; i < 10; i++){hThreadW[i] = (HANDLE)_beginthreadex(NULL, 0, MultiWriterThreadFun, NULL, 0, NULL);  }WaitForMultipleObjects(10, hThreadR, TRUE, INFINITE);  WaitForMultipleObjects(10, hThreadW, TRUE, INFINITE);for (int i = 0; i < 10; i++)  {CloseHandle(hThreadR[i]); CloseHandle(hThreadW[i]);}CloseHandle(g_hEmpty);  CloseHandle(g_hFull);  ConsolePrintBlue("循环队列中保存的数为:\n");for (int i = 0; i < QUEUE_LEN; i++){printf("%-6d", g_queue[i]);}printf("\n");DeleteCriticalSection(&g_cs);  ConsolePrintBlue("\\----- end ------\n\n\n");}void main()  {  ConsolePrintBlue("----------- 基于win32平台下编写多线程操作 -----------\n\n");//创建线程,关闭线程,挂起线程ConsolePrintBlue("\n\n\n----------- 1:创建线程,关闭线程,挂起线程 -----------\n\n");ThreadexTest();//使用临界资源,互斥锁,信号量,事件ConsolePrintBlue("\n\n\n\n\n----------- 2:使用临界资源,互斥锁,信号量,事件 -----------\n\n");CriticalSectionTest(); SrwLockTest(); SemaphoreTest(); EventTest();//读者写者问题ConsolePrintBlue("\n\n\n\n\n----------- 3:读者写者问题 -----------\n\n"); SingleReaderSingleWirterTest(); MultiReaderSingleWirterTest();MultiReaderMultiReaderWriterTest();} 

0 0
原创粉丝点击