溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

VC++線程同步(五) 信號量使用例子

發(fā)布時間:2020-07-16 11:30:26 來源:網(wǎng)絡 閱讀:1998 作者:超級極客 欄目:編程語言

                    信號量(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)。

VC++線程同步(五) 信號量使用例子


有不懂的連續(xù)我qq:2438746951

交流群:140066160


源代碼地址:http://down.51cto.com/data/2329794









向AI問一下細節(jié)

免責聲明:本站發(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)容。

AI