include "stdafx.h"
#include
#include
#include
//设置控制台输出颜色
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]); //恢复线程0
SuspendThread(hThread[1]); //挂起线程1
Sleep(510); //主线程挂起510毫秒,期间线程0正好可以输出5次
//终止线程0的运行
TerminateThread(hThread[0], 0); //并不保证线程被终止,最好采用线程函数返回方式终止
ResumeThread(hThread[1]); //恢复线程1
WaitForSingleObject(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,最大计数为1
for(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();
}