临界区、事件、互斥量、 信号量--四种控制多线程同步与互斥的方法
2015-04-13 17:25
363 查看
// MultiThread.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <Windows.h> #include <stdlib.h> #include <stdio.h> #include <iostream> #include <process.h> using namespace std; CRITICAL_SECTION g_csA; CRITICAL_SECTION g_csB; UINT WINAPI PrintThread1(LPVOID lp) { while (1) { //该代码段最后看,用信号量实现10个线程同步有序 //if (WaitForSingleObject(g_hDemaphore, INFINITE) != WAIT_OBJECT_0) //{ //continue; //} // EnterCriticalSection(&g_csA); for (int i=0;i<3;i++) { printf("thread1\n"); Sleep(1000); } printf("\n"); LeaveCriticalSection(&g_csA); } return 0; } UINT WINAPI PrintThread2(LPVOID lp) { while (1) { EnterCriticalSection(&g_csA); for (int i=0;i<3;i++) { printf("thread2\n"); Sleep(100); } printf("\n"); LeaveCriticalSection(&g_csA); } return 0; } /////////////////////////////////////////////////// HANDLE g_hEvent; UINT WINAPI PrintThread3(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hEvent, INFINITE); if (dwResult == WAIT_OBJECT_0) { for (int i=0;i<3;i++) { printf("thread3\n"); Sleep(500); } printf("\n"); } SetEvent(g_hEvent); } return 0; } UINT WINAPI PrintThread4(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hEvent, INFINITE); if (dwResult == WAIT_OBJECT_0) { for (int i=0;i<3;i++) { printf("thread4\n"); Sleep(300); } printf("\n"); } SetEvent(g_hEvent); } return 0; } /////////////////////////////////////////////////////////////// HANDLE g_hMutex; UINT WINAPI PrintThread5(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hMutex, 500);//当前线程拥有该互斥量 if (dwResult == WAIT_OBJECT_0) { for (int i=0;i<3;i++) { printf("thread5\n"); Sleep(200); } printf("\n"); } if (!ReleaseMutex(g_hMutex))//当前线程释放该互斥量 { DWORD dwError = GetLastError(); if (dwError == ERROR_NOT_OWNER) { printf("thread5 error:ERROR_NOT_OWNER\n"); } else { printf("thread5 error:%d\n", dwError); } } } return 0; } UINT WINAPI PrintThread6(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hMutex, 1000); if (dwResult == WAIT_OBJECT_0) { for (int i=0;i<3;i++) { printf("thread6\n"); Sleep(400); } printf("\n"); } if (!ReleaseMutex(g_hMutex)) //如果互斥量被线程5占有,那么当前线程将无法释放,只有占有者可以释放 { DWORD dwError = GetLastError(); if (dwError == ERROR_NOT_OWNER) { printf("thread6 error:ERROR_NOT_OWNER\n"); } else { printf("thread6 error:%d\n", dwError); } } } return 0; } ////////////////////////////////////////////////////////////// HANDLE g_hDemaphore; UINT WINAPI PrintThread7(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);//占用一个资源计数 if (dwResult == WAIT_OBJECT_0) { printf("Anglela"); Sleep(1000); } LONG count; ReleaseSemaphore(g_hDemaphore,1,&count);//释放一个资源计数 } return 0; } UINT WINAPI PrintThread8(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hDemaphore, INFINITE);//减少一个资源计数(如果还有资源计数) if (dwResult == WAIT_OBJECT_0) { printf("Baby\n"); printf("\n"); Sleep(1000); } LONG count; ReleaseSemaphore(g_hDemaphore,1,&count);//增加一个资源计数 Sleep(2000);// 减少后并不立即增加 } return 0; } UINT WINAPI PrintThread9(LPVOID lp) { while (1) { DWORD dwResult = WaitForSingleObject(g_hDemaphore, INFINITE); Sleep(1000); if (dwResult == WAIT_OBJECT_0) { printf("Alice "); Sleep(500); } LONG count; BOOL bFlag = ReleaseSemaphore(g_hDemaphore,3,&count); if (!bFlag) { printf("\n"); printf("thread9 release failed:%d\n", GetLastError()); } } return 0; } UINT WINAPI PrintThread10(LPVOID lp) { DWORD dwResult = 0; while (1) { //减少2个资源计数 dwResult = WaitForSingleObject(g_hDemaphore, INFINITE); dwResult = WaitForSingleObject(g_hDemaphore, INFINITE); if (dwResult == WAIT_OBJECT_0) { printf("in Wonderland\n"); printf("\n"); Sleep(1000); } ::EnterCriticalSection(&g_csB); LONG count;// if rcount+pcount>maxcount,增加资源计数失败且当前资源计数不变 BOOL bFlag = ReleaseSemaphore(g_hDemaphore,2/*relasecount*/,&count/*previous count*/);//增加2个资源计数 if (!bFlag) { printf("\n"); printf("thread10 release failed:%d\n", GetLastError()); } printf("thread10 previous count:%d\n", count);//执行release以前的资源计数 ::LeaveCriticalSection(&g_csB); } return 0; } // 除了临界区,其他为内核对象,除了用于线程还可用于进程,可以通过创建时指定的名字打开夸进程使用 ////////////////////////////////////////////////////////////// int _tmain(int argc, _TCHAR* argv[]) { InitializeCriticalSection(&g_csA); InitializeCriticalSection(&g_csB); HANDLE m_hThread = NULL; //同步与互斥:‘1个生产者-N个消费者’模型,同步有序-必须先生产然后消费,互斥无序,要么执行A,要么执行B,AB顺序未知 //由于线程1比线程2先执行,临界区保证打印结果thread1,thread2有序 //m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread1, NULL, 0, NULL); //m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread2, NULL, 0, NULL); //使用事件控制线程3,4有序执行 //创建一个命名的自动重置事件内核对象,第二个参数FALSE指定自动重置,第三个参数TRUE设置初始化为有信号 g_hEvent=CreateEvent(NULL,FALSE,TRUE,LPCWSTR("myevent")); if (g_hEvent) { if (ERROR_ALREADY_EXISTS==GetLastError()) { printf("error:event alread exist\n"); } } // 可以打开其他进程创建的事件对象 //$ g_hEvent = OpenEventA(EVENT_ALL_ACCESS, TRUE, LPCWSTR("myevent")); //$ ResetEvent(g_hEvent); //m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread3, NULL, 0, NULL); //m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread4, NULL, 0, NULL); //第二个参数TRUE,main线程拥有互斥量,体现互斥量‘线程拥有’的概念,区别事件‘先到先得’ g_hMutex = CreateMutexA(NULL, TRUE, "mymutex"); //$ g_hMutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, "mymutex"); /*m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread5, NULL, 0, NULL); m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread6, NULL, 0, NULL); //$ 事件对象设置为自动重置与互斥量有类似功能 Sleep(3000); printf("main thread release mutex\n"); printf("\n"); ReleaseMutex(g_hMutex);*/ // 信号量体现‘资源计数’的概念,通过修改初始计数与释放增加计算使打印有序 // SEMAPHORE_MODIFY_STATE,初始资源计数为2时,信号量为有信号状态,最大允许资源计数为10时,信号量为有信号状态 g_hDemaphore=CreateSemaphoreA(NULL,2,10,("Sem"));//初始资源计数为1,最大允许资源计数为2,通过release增加资源计数 //$ HANDLE semaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, _T("Global\\TestSemaphore")); m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread7, NULL, 0, NULL); m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread8, NULL, 0, NULL); m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread9, NULL, 0, NULL); m_hThread =(HANDLE)_beginthreadex(NULL, 0, PrintThread10, NULL, 0, NULL); //////////////////////////////////////////////////////////////////////// while (getchar()!='x') { } DeleteCriticalSection(&g_csA); DeleteCriticalSection(&g_csB); CloseHandle(m_hThread); CloseHandle(g_hEvent); if (WaitForSingleObject(g_hMutex, 0) == WAIT_ABANDONED) { ReleaseMutex(g_hMutex); } CloseHandle(g_hMutex); return 0; }
1.线程1,2实现打印thread1,thread2有序,thread3~thread6实现类似打印功能;
2.线程7,8,9,10实现打印两个有序字符串,通过修改初始计数与增减计数实现打印有序;
3.MFC将4方法封装4个类功能相同,除了临界区,其他3个可以进程间使用。
相关文章推荐
- 多线程同步方法:临界区、事件、信号量、互斥对象
- 临界区、互斥量、事件、信号量四种方式
- 同步互斥,信号量,互斥量,事件,临界区
- 互斥同步-临界区,互斥量,信号量,事件的区别
- 多线程同步的三种方法-互斥量-事件对象-关键代码段(临界区)
- 进程与线程;同步与互斥:事件,信号量,临界区,互斥量
- Delphi关于多线程同步的一些方法,信号量,互斥量和临界区
- 互斥同,-临界区,互斥量,信号量,事件
- win32下多线程同步方式之临界区,互斥量,事件对象,信号量
- 四种进程或线程同步互斥的控制方法介绍
- 信号量,互斥量,事件,临界区有什么区别?
- VC++中四种进程或线程同步互斥的控制方法
- 四种进程或线程同步互斥的控制方法
- 进程间的多线程同步事件控制方法
- 临界区,互斥量,信号量,事件的区别
- Visual C++线程同步技术剖析:临界区,事件,信号量,互斥量
- 四种进程或线程同步互斥的控制方法
- C++中四种进程或线程同步互斥的控制方法
- 四种进程或线程同步互斥的控制方法
- VC下线程同步的三种方法(互斥、事件、临界区)