您好,登錄后才能下訂單哦!
信號量(Semaphore)
信號量是內核對象,使用幾個形象的例子,進行描述.
1 假設有5個位置,而外面有很多人要進來,那么當5個位置被人占用了
后,其他人就必須排隊等待,每個人使用時間不同,5個占用的位置,其中有兩個完成了,那么,排隊的人中,最前面的兩個人進行可以使用,但是最多就是5個人同時能夠使用,這就是信號量.
2 例如我們在服務器中創建了一個線程池,它由5個線程組成,也就意味著,最多同時處理5個請求,一旦超過5個,那么請求就放入緩沖中,當一個或多個請求(最多5個)完成后,那么從緩沖中拿出其他的請求進行處理.
信號量的特點:
1 信號量同來對資源進行計數
2 包含一個使用計數器,一個最大資源計數器,和一個當前資源計數器
3 最大資源計數器用來控制最大的子元素
4 當前資源計數器表示當前可用的資源數量
觸發規則和當前資源計數器是相關的。
觸發規則:
1 如果當前資源>0則信號量處于觸發狀態
2 如果當前資源=0,則信號量處于未觸發狀態
3 系統絕對不會讓當前資源技術變為負值
4 當前資源計數絕對不會大于最大資源計數
運行流程:
1 假設我們創建了一個信號量,它的最大資源計數為5,且當前資源計數
也為5(一般都是在初始化過程中間最大的資源計數值和當前資源計數值是相同的) 由于當前資源計數器大于0,說明信號量處于觸發狀態.
2 為了獲取對被保護的資源的訪問權,線程會調用wait函數,并轉入信號量的句柄,在內部,等待函數會檢測當前資源計數器 技術,如果大于
0(大于0觸發狀態)那么等待函數會將當前資源計數器減1并讓調用線程
繼續運行,如果等于0(未觸發狀態)那么系統會讓線程進入等待狀態(不消化cpu),當另外一個線程將信號量的當前資源計數遞增時,系統會
記得哪些線程在等待,使他們編程可調度狀態(并相應的遞減當前資源計數)
3 線程通過releaseSemaphore來遞增信號量的當前資源計數器.
來看代碼:
全局變量 HANDLE g_hSem;
創建一個信號量CreateSemaphore(NULL,2,2,NULL);
參數1 windows。。權限
參數2 代表當前資源計數值
參數3 最大資源計數器,表示信號量同時可以管理2個線程
參數4 對象名...
應為創建的時候,當前的資源計數大于0,所以他是觸發狀態的。
創建5個線程,用5個線程競爭兩個位置,體現一下競爭的激烈.
case WM_CREATE: { //系統中基于對話框字體的高度 int cyChar = HIWORD(GetDialogBaseUnits()); thrParams4.hwnd = hWnd; thrParams4.cyChar = cyChar; //創建信號量 g_hSem = CreateSemaphore(NULL, 2, 2,NULL); HANDLE handleEmployee1 = CreateThread(NULL, 0, ThrEmployeeProc1, &thrParams4, 0, NULL); HANDLE handleEmployee2 = CreateThread(NULL, 0, ThrEmployeeProc2, &thrParams4, 0, NULL); HANDLE handleEmployee3 = CreateThread(NULL, 0, ThrEmployeeProc3, &thrParams4, 0, NULL); HANDLE handleEmployee4 = CreateThread(NULL, 0, ThrEmployeeProc4, &thrParams4, 0, NULL); HANDLE handleEmployee5 = CreateThread(NULL, 0, ThrEmployeeProc5, &thrParams4, 0, NULL); //關閉線程句柄 CloseHandle(handleEmployee1); CloseHandle(handleEmployee2); CloseHandle(handleEmployee3); CloseHandle(handleEmployee4); CloseHandle(handleEmployee5); } case WM_DESTROY: //關閉信號量 CloseHandle(g_hSem); PostQuitMessage(0); break;
來看一下線程函數吧.
DWORD WINAPI ThrEmployeeProc1(LPVOID lp) { PPARAMS param4 = static_cast<PPARAMS>(lp); //等待這個信號量 永遠阻塞 如果信號量的 當前資源計數 大于0 就觸發 反悔 WaitForSingleObject(g_hSem,INFINITE); //當他返回的時候 當前資源計數會 減1 //休眠2秒 Sleep(2000); //獲取當前毫秒數 DWORD dwCurTime = GetTickCount(); //獲得DC HDC hdc = GetDC(param4->hwnd); //顯示文本 BOOL bF = TextOut(hdc, 0, (g_iLine4++)*param4->cyChar, _T("員工線程1正在使用公司上網"), lstrlen(_T("員工線程1正在使用公司上網"))); //釋放dc ReleaseDC(param4->hwnd,hdc); //循環10秒退出 while (true) { if ((GetTickCount() - dwCurTime) > 1000 * 10) { HDC hdc = GetDC(param4->hwnd); SetTextColor(hdc, RGB(255, 0, 0)); TextOut(hdc, 0, (g_iLine4++)*param4->cyChar, _T("員工線程1已經沒有使用公司上網"), lstrlen(_T("員工線程1已經沒有使用公司上網"))); ReleaseDC(param4->hwnd, hdc); break; } Sleep(1000); } //釋放信號量 信號量句柄 穿進去 并且 // 1代表加1 當前資源計數器+1 可以+2 +3 但是現在加1最合適 // 最后一個參數是反回上一次資源計數器的數量 大部分情況下 不需要這個東西 ReleaseSemaphore(g_hSem,1,NULL); return 0; }
效果:
我們發現 這個上網的數量,是通過信號量被控制住了,每次最多
可以有兩個員工可以上網。
有不懂的連續我qq:2438746951
交流群:140066160
源代碼地址:http://down.51cto.com/data/2329794
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。