临界区、事件、互斥量、 信号量--四种控制多线程同步与互斥的方法
生活随笔
收集整理的這篇文章主要介紹了
临界区、事件、互斥量、 信号量--四种控制多线程同步与互斥的方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
// 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個可以進程間使用。
總結
以上是生活随笔為你收集整理的临界区、事件、互斥量、 信号量--四种控制多线程同步与互斥的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++二维数组讲解、二维数组的声明和初始
- 下一篇: VC++ 进程间通信方法总结