国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
孫鑫VC視頻教程筆記之第十六課(上)“線程同步”

線程同步有三種方式:

1.      互斥對(duì)象涉及方法:

HANDLE hMutex=CreateMutex(NULL,FALSE,NULL); //第二個(gè)參數(shù)為FALSE,將互斥對(duì)象聲明為空閑狀態(tài)

WaitForSingleObject(hMutex,INFINITE); //第二個(gè)參數(shù)為INFINITE表示一直等待,直到擁有互斥對(duì)象

ReleaseMutex(hMutex); //使用完了,將互斥對(duì)象還給操作系統(tǒng)

      具體代碼及各種情況的分析見(jiàn)上一章,這里就不再敘述。

 

2.      事件對(duì)象:

事件對(duì)象也屬于內(nèi)核對(duì)象,包含一個(gè)使用計(jì)數(shù),一個(gè)用于指明該事件是一個(gè)自動(dòng)重置的事件還是一個(gè)人工重置的事件的布爾值,另一個(gè)用于指明該事件處于可用狀態(tài)還是不可用的布爾值。

有兩種不同類(lèi)型的事件對(duì)象。一種是人工重置的事件,另一種是自動(dòng)重置的事件。當(dāng)人工重置的事件得到通知時(shí),等待該事件的所有線程均變?yōu)榭烧{(diào)度線程。當(dāng)一個(gè)自動(dòng)重置的事件得到通知時(shí),等待該事件的線程中只有一個(gè)線程變?yōu)榭烧{(diào)度線程。所以?xún)?yōu)先選擇自動(dòng)重置的事件。

 

說(shuō)明:CreateEvent方法第一個(gè)參數(shù)是關(guān)于的安全的結(jié)構(gòu)體,一般設(shè)置為NULL;第二個(gè)參數(shù)表示是人工重置還是自動(dòng)重置,TRUE代表人工重置;第三個(gè)參數(shù)表示當(dāng)前狀態(tài)是可用還是不可用;第四個(gè)參數(shù)表示Event名稱(chēng),NULL的話,默認(rèn)。

HANDLE g_hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

以下代碼會(huì)出現(xiàn)異常:在將CreateEvent的第二個(gè)參數(shù)設(shè)置為人工重置的時(shí)候,因?yàn)榈却撌录乃芯€程均變?yōu)榭烧{(diào)度線程,所以發(fā)現(xiàn)售票實(shí)例程序最終會(huì)出現(xiàn)0。所以最好還是選擇自動(dòng)重置的事件。

#include <windows.h>

#include <iostream.h>

 

DWORD WINAPI ThreadProc1(LPVOID lpParameter);

DWORD WINAPI ThreadProc2(LPVOID lpParameter);

 

int ticket=100;

HANDLE g_hEvent;

 

void main()

{

      HANDLE handle1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);

      HANDLE handle2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);

      CloseHandle(handle1);

      CloseHandle(handle2);

     

      g_hEvent=CreateEvent(NULL,TRUE,TRUE,NULL);

 

      Sleep(4000);

      CloseHandle(g_hEvent);

}

 

DWORD WINAPI ThreadProc1(LPVOID lpParameter)

{

      while(TRUE)

      {

           WaitForSingleObject(g_hEvent,INFINITE); //第二個(gè)參數(shù)為INFINITE表示一直等待,直到擁有互斥對(duì)象

           if(ticket>0)

           {

                 Sleep(1);

                 cout<<"thread1 sale the ticket id is:"<<ticket--<<endl;

           }

           else

                 break;

      }

      return 0;

}

 

DWORD WINAPI ThreadProc2(LPVOID lpParameter)

{

      while(TRUE)

      {

           WaitForSingleObject(g_hEvent,INFINITE);

           if(ticket>0)

           {

                 Sleep(1);

                 cout<<"thread2 sale the ticket id is:"<<ticket--<<endl;

           }

           else

                 break;

      }

      return 0;

}

 

 

說(shuō)明:

如果一個(gè)線程循環(huán)內(nèi)部已經(jīng)調(diào)用了WaitForSingleObject(g_hEvent,INFINITE);但是在單個(gè)循環(huán)完成前沒(méi)有調(diào)用SetEvent(g_hEvent)將狀態(tài)設(shè)置成可用的話,下一次進(jìn)入循環(huán)時(shí)再次調(diào)用WaitForSingleObject時(shí)發(fā)現(xiàn)狀態(tài)不可用,所以一直等待,代碼例子將上面的代碼g_hEvent=CreateEvent(NULL,TRUE,TRUE,NULL);修改為g_hEvent=CreateEvent(NULL,FALSE,TRUE,NULL);則會(huì)出現(xiàn)這個(gè)問(wèn)題,其結(jié)果就是僅僅線程1售出了100這張票。如果在循環(huán)退出前調(diào)用SetEvent(g_hEvent);則問(wèn)題可以解決。

 

綜上所述,涉及到的方法:

HANDLE g_hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

WaitForSingleObject(g_hEvent,INFINITE); //等待事件,如果事件可用,運(yùn)行下面的代碼,并且將事件狀態(tài)設(shè)置為不可用狀態(tài),如果事件不可用,一直等待。

SetEvent(g_hEvent)  //將事件設(shè)置為可用的狀態(tài)

ResetEvent(g_hEvent) //將事件設(shè)置為不可用狀態(tài)

一般情況下WaitForSingleObjectSetEvent配對(duì)使用。

 

3.      關(guān)鍵代碼段:

關(guān)鍵代碼段(臨界區(qū))是指一個(gè)小代碼段,在代碼能夠執(zhí)行前,它必須獨(dú)占對(duì)某些資源的訪問(wèn)權(quán)。

            可以將關(guān)鍵代碼段想象成電話亭資源:

           CRITICAL_SECTION g_cs;

           InitializeCriticalSection(&g_cs); //創(chuàng)建電話亭資源,一般放在構(gòu)造函數(shù)中

           EnterCriticalSection(&g_cs); //判斷關(guān)鍵資源所有權(quán)是否可用,可用則進(jìn)入

           LeaveCriticalSection(&g_cs);使用完關(guān)鍵資源后,釋放所有權(quán)

           DeleteCriticalSection(&g_cs); //銷(xiāo)毀電話亭資源,一般放在析構(gòu)函數(shù)中

      其中InitializeCriticalSectionDeleteCriticalSection配對(duì)使用;

      EnterCriticalSectionLeaveCriticalSection配對(duì)使用,中間存放訪問(wèn)共享資源的代碼。

 

4.      互斥對(duì)象、事件對(duì)象與關(guān)鍵代碼段的比較

互斥對(duì)象和事件對(duì)象屬于內(nèi)核對(duì)象,利用內(nèi)核對(duì)象進(jìn)行線程同步,速度較慢,但利用互斥對(duì)象和事件對(duì)象這樣的內(nèi)核對(duì)象,可以在多個(gè)進(jìn)程中的各個(gè)線程間進(jìn)行同步。

關(guān)鍵代碼段是工作在用戶方式下,同步速度較快,但在使用關(guān)鍵代碼段時(shí),很容易進(jìn)入死鎖狀態(tài),因?yàn)樵诘却M(jìn)入關(guān)鍵代碼段時(shí)無(wú)法設(shè)定超時(shí)值。

 

5.      死鎖:

哲學(xué)家進(jìn)餐的問(wèn)題:每個(gè)哲學(xué)家手中只有一根筷子,要進(jìn)餐必須有兩根,但誰(shuí)也不愿意先給出自己的那根給別人。大家都處于等待狀態(tài)。

線程1擁有了臨界區(qū)對(duì)象A,等待臨界區(qū)對(duì)象B的擁有權(quán),線程2擁有了臨界區(qū)對(duì)象B,等待臨界區(qū)對(duì)象A的擁有權(quán),就造成了死鎖。

死鎖代碼:

#include <windows.h>

#include <iostream.h>

 

DWORD WINAPI ThreadProc1(LPVOID lpParameter);

DWORD WINAPI ThreadProc2(LPVOID lpParameter);

 

int ticket=100;

 

//創(chuàng)建兩個(gè)關(guān)鍵資源

CRITICAL_SECTION g_cs1;

CRITICAL_SECTION g_cs2;

 

void main()

{

      HANDLE handle1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);

      HANDLE handle2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);

      CloseHandle(handle1);

      CloseHandle(handle2);

     

      InitializeCriticalSection(&g_cs1);

      InitializeCriticalSection(&g_cs2);

 

      Sleep(4000);

      DeleteCriticalSection(&g_cs1);

      DeleteCriticalSection(&g_cs2);

}

 

DWORD WINAPI ThreadProc1(LPVOID lpParameter)

{

      while(TRUE)

      {

           EnterCriticalSection(&g_cs1);

           Sleep(1);

           EnterCriticalSection(&g_cs2);

           if(ticket>0)

           {

                 Sleep(1);

                 cout<<"thread1 sale the ticket id is:"<<ticket--<<endl;

           }

           else

                 break;

           LeaveCriticalSection(&g_cs1);

           LeaveCriticalSection(&g_cs2);

      }

      return 0;

}

 

DWORD WINAPI ThreadProc2(LPVOID lpParameter)

{

      while(TRUE)

      {

           EnterCriticalSection(&g_cs2);

           Sleep(1);

           EnterCriticalSection(&g_cs1);

           if(ticket>0)

           {

                 Sleep(1);

                 cout<<"thread2 sale the ticket id is:"<<ticket--<<endl;

           }

           else

                 break;

           LeaveCriticalSection(&g_cs1);

           LeaveCriticalSection(&g_cs2);

      }

      return 0;

}

 

說(shuō)明:首先線程1得到資源1的所有權(quán),然后睡眠1毫秒,線程1就讓出了執(zhí)行權(quán),這個(gè)時(shí)候線程2得到執(zhí)行權(quán),運(yùn)行,得到資源2的所有權(quán),線程2然后睡眠1毫秒,線程2就讓出了執(zhí)行權(quán),這個(gè)時(shí)候線程1得到執(zhí)行權(quán),線程1繼續(xù)執(zhí)行,想得到資源2的資源,但發(fā)現(xiàn)資源2被線程1所占用,等待。當(dāng)線程1的事件片過(guò)了以后,線程2得到執(zhí)行權(quán),繼續(xù)執(zhí)行,想得到資源1的所有權(quán),但發(fā)現(xiàn)資源1被線程1占用,所以也繼續(xù)等待,這樣線程1和線程2都互相等待,造成死鎖。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
MFC(線程同步與異步套接字,孫鑫
Overlapped I/O模型深入分析
WinCE 控制面板和驅(qū)動(dòng)通信 .
Windows下C++多線程同步與互斥簡(jiǎn)單運(yùn)用
多線程同步-event
C/C 臨界量
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服