日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题

發布時間:2024/4/11 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

秒殺多線程第十五篇 關鍵段,事件,互斥量,信號量的“遺棄”問題

在《秒殺多線程第九篇 經典線程同步總結 關鍵段 事件 互斥量 信號量》中對經典多線程同步互斥問題進行了回顧和總結,這篇文章對Windows系統下常用的線程同步互斥機制——關鍵段事件互斥量信號量進行了總結。有網友問到互斥量能處理“遺棄”問題,事件和信號量是否也能處理“遺棄”問題。因此本文將對事件和信號量作個試驗,看看事件和信號量能否處理“遺棄”問題。

?

一.什么是“遺棄”問題

在《秒殺多線程第七篇 經典線程同步 互斥量Mutex》講到了互斥量能處理“遺棄”問題,下面引用原文:

互斥量常用于多進程之間的線程互斥,所以它比關鍵段還多一個很有用的特性——“遺棄”情況的處理。比如有一個占用互斥量的線程在調用ReleaseMutex()觸發互斥量前就意外終止了(相當于該互斥量被“遺棄”了),那么所有等待這個互斥量的線程是否會由于該互斥量無法被觸發而陷入一個無窮的等待過程中了?這顯然不合理。因為占用某個互斥量的線程既然終止了那足以證明它不再使用被該互斥量保護的資源,所以這些資源完全并且應當被其它線程來使用。因此在這種“遺棄”情況下,系統自動把該互斥量內部的線程ID設置為0,并將它的遞歸計數器復置為0,表示這個互斥量被觸發了。然后系統將公平地選定一個等待線程來完成調度(被選中的線程的WaitForSingleObject()會返回WAIT_ABANDONED_0

可見“遺棄”問題就是——占有某種資源的進程意外終止后,其它等待該資源的進程能否感知。

?

二.關鍵段的“遺棄”問題

關鍵段在這個問題上很簡單——由于關鍵段不能跨進程使用,所以關鍵段不需要處理“遺棄”問題。

?

三.事件,互斥量,信號量的“遺棄”問題

事件,互斥量,信號量都是內核對象,可以跨進程使用。一個進程在創建一個命名的事件后其它進程可以調用OpenEvent()并傳入事件的名稱來獲得這個事件的句柄。因此事件,互斥量和信號量都會遇到“遺棄”問題。我們已經知道互斥量能夠處理“遺棄”問題,接下來就來看看事件和信號量是否能夠處理“遺棄”問題。類似于秒殺多線程第七篇 經典線程同步互斥量Mutex對互斥量所做的試驗,下面也對事件和信號量作同樣的試驗:

1.?創建二個進程。

2.?進程一創建一個初始為未觸發的事件,然后等待按鍵,按下y則觸發事件后結束進程,否則直接退出表示進程一已意外終止。

3.?進程二先獲得事件的句柄,然后調用WaitForSingleObject()等待這個事件10秒,在這10秒內如果事件已經觸發則輸出“已收到信號”,否則輸出“未在規定的時間內收到信號”。如果在等待的過程中進程一意外終止,則輸出擁有事件的進程意外終止。信號量的試驗方法類似。

為了加強對比效果,將互斥量的試驗結果先展示出來(代碼請參見《秒殺多線程第七篇經典線程同步 互斥量Mutex》)

可以看出在第一個進程在沒有觸發互斥量就直接退出的情況下,等待這個互斥量的第二個進程是能夠感知進程一所發生的意外終止的。

接下來就先完成事件的“遺棄”問題試驗代碼。

進程一:

[cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<conio.h>??
  • #include?<windows.h>??
  • const?TCHAR?STR_EVENT_NAME[]?=?TEXT("Event_MoreWindows");??
  • int?main()??
  • {??
  • ????printf("?????經典線程同步?事件的遺棄處理??進程一\n");????
  • ????printf("?--?by?MoreWindows(?http://blog.csdn.net/MoreWindows?)?--\n\n");????
  • ????HANDLE?hEvent?=?CreateEvent(NULL,?FALSE,?FALSE,?STR_EVENT_NAME);//自動置位?當前未觸發??
  • ????printf("事件已經創建,現在按y觸發事件,按其它鍵終止進程\n");??
  • ????char?ch;??
  • ????scanf("%c",?&ch);??
  • ????if?(ch?!=?'y')??
  • ????????exit(0);?//表示進程意外終止??
  • ????SetEvent(hEvent);??
  • ????printf("事件已經觸發\n");??
  • ????CloseHandle(hEvent);??
  • ????return?0;??
  • }??
  • 進程二:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<windows.h>??
  • const?TCHAR?STR_EVENT_NAME[]?=?TEXT("Event_MoreWindows");??
  • int?main()??
  • {??
  • ????printf("?????經典線程同步?事件的遺棄處理??進程二\n");????
  • ????printf("?--?by?MoreWindows(?http://blog.csdn.net/MoreWindows?)?--\n\n");????
  • ??
  • ????HANDLE?hEvent?=?OpenEvent(EVENT_ALL_ACCESS,?TRUE,?STR_EVENT_NAME);?//打開事件??
  • ????if?(hEvent?==?NULL)??
  • ????{??
  • ????????printf("打開事件失敗\n");??
  • ????????return?0;??
  • ????}??
  • ????printf("?等待中....\n");??
  • ????DWORD?dwResult?=?WaitForSingleObject(hEvent,?10?*?1000);?//等待事件被觸發??
  • ????switch?(dwResult)??
  • ????{??
  • ????case?WAIT_ABANDONED:??
  • ????????printf("擁有事件的進程意外終止\n");??
  • ????????break;??
  • ??
  • ????case?WAIT_OBJECT_0:??
  • ????????printf("已經收到信號\n");??
  • ????????break;??
  • ??
  • ????case?WAIT_TIMEOUT:??
  • ????????printf("未在規定的時間內收到信號\n");??
  • ????????break;??
  • ????}??
  • ????CloseHandle(hEvent);??
  • ????return?0;??
  • }??
  • 事件Event試驗結果1-進程一觸發事件后正常結束:

    事件Event試驗結果2-進程一意外終止:

    可以看出進程二沒能感知進程一意外終止,說明事件不能處理“遺棄”問題。

    ?

    下面再來試下信號量。

    信號量的“遺棄”問題試驗代碼:

    進程一:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<conio.h>??
  • #include?<windows.h>??
  • const?TCHAR?STR_SEMAPHORE_NAME[]?=?TEXT("Semaphore_MoreWindows");??
  • int?main()??
  • {??
  • ????printf("?????經典線程同步?信號量的遺棄處理??進程一\n");????
  • ????printf("?--?by?MoreWindows(?http://blog.csdn.net/MoreWindows?)?--\n\n");????
  • ??
  • ????HANDLE?hSemaphore?=?CreateSemaphore(NULL,?0,?1,?STR_SEMAPHORE_NAME);//當前0個資源,最大允許1個同時訪問??
  • ????printf("信號量已經創建,現在按y觸發信號量,按其它鍵終止進程\n");??
  • ????char?ch;??
  • ????scanf("%c",?&ch);??
  • ????if?(ch?!=?'y')??
  • ????????exit(0);?//表示進程意外終止??
  • ????ReleaseSemaphore(hSemaphore,?1,?NULL);??
  • ????printf("信號量已經觸發\n");??
  • ????CloseHandle(hSemaphore);??
  • ????return?0;??
  • }??
  • 進程二:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #include?<windows.h>??
  • const?TCHAR?STR_SEMAPHORE_NAME[]?=?TEXT("Semaphore_MoreWindows");??
  • int?main()??
  • {??
  • ????printf("?????經典線程同步?信號量的遺棄處理??進程二\n");????
  • ????printf("?--?by?MoreWindows(?http://blog.csdn.net/MoreWindows?)?--\n\n");????
  • ??
  • ????HANDLE?hSemaphore?=?OpenSemaphore?(SEMAPHORE_ALL_ACCESS,?TRUE,?STR_SEMAPHORE_NAME);?//打開信號量??
  • ????if?(hSemaphore?==?NULL)??
  • ????{??
  • ????????printf("打開信號量失敗\n");??
  • ????????return?0;??
  • ????}??
  • ????printf("?等待中....\n");??
  • ????DWORD?dwResult?=?WaitForSingleObject(hSemaphore,?10?*?1000);?//等待信號量被觸發??
  • ????switch?(dwResult)??
  • ????{??
  • ????case?WAIT_ABANDONED:??
  • ????????printf("擁有信號量的進程意外終止\n");??
  • ????????break;??
  • ??
  • ????case?WAIT_OBJECT_0:??
  • ????????printf("已經收到信號\n");??
  • ????????break;??
  • ??
  • ????case?WAIT_TIMEOUT:??
  • ????????printf("未在規定的時間內收到信號\n");??
  • ????????break;??
  • ????}??
  • ????CloseHandle(hSemaphore);??
  • ????return?0;??
  • }??
  • 信號量Semaphore試驗結果1-進程一觸發信號量后正常結束

    信號量Semaphore試驗結果2-進程一意外終止

    可以看出進程二沒能感知進程一意外終止,說明信號量與事件一樣都不能處理“遺棄”問題。

    ?

    四.“遺棄”問題總結

    由本文所做的試驗可知,互斥量能夠處理“遺棄”情況,事件與信號量都無法解決這一情況。

    再思考下互斥量能處理“遺棄”問題的原因,其實正是因為它有“線程所有權”概念。在系統中一旦有線程結束后,系統會判斷是否有互斥量被這個線程占有,如果有,系統會將這互斥量對象內部的線程ID號將設置為NULL,遞歸計數設置為0,這表示該互斥量已經不為任何線程占用,處于觸發狀態。其它等待這個互斥量的線程就能順利執行下去了。至于線程如何獲取互斥量的“線程所有權”,MSDN上介紹為——A thread obtainsownership of a mutex either by creating it with the?bInitialOwnerparameter set to?TRUE?or by specifying its handle in a call toone of the?wait functions.

    文章到這就結束了,有問題歡迎留言或發送郵件:morewindows@126.com

    ?

    ?

    ?

    轉載請標明出處,原文地址:http://blog.csdn.net/morewindows/article/details/7823572

    如果覺得本文對您有幫助,請點擊支持一下,您的支持是我寫作最大的動力,謝謝。

    ?

    ?

    ?

    最后號外一下:《白話經典算法系列之七大排序》已經整理出電子書形式了,歡迎大家下載,下載地址:http://download.csdn.net/detail/morewindows/4443208

    總結

    以上是生活随笔為你收集整理的秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。