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