本文为【WIN32下DELPHI中的多线程【同步2】(五)】的汉字拼音对照版显示拼音
线xian程cheng同tong步bu2
上shang一yi文wen中zhong曾zeng经jing介jie绍shao了le线xian程cheng同tong步bu的de一yi些xie方fang法fa,其qi实shi完wan成cheng同tong步bu还huan有you很hen多duo很hen多duo的de办ban法fa,这zhe里li最zui后hou介jie绍shao一yi种zhong方fang式shi--信xin号hao量liang内nei核gai对dui象xiang。并bing借jie此ci来lai回hui顾gu线xian程cheng同tong步bu。
在zai谈tan论lun信xin号hao量liang之zhi前qian,我wo想xiang先xian谈tan论lun另ling外wai一yi种zhong方fang式shi,一yi种zhong你ni最zui好hao不bu要yao使shi用yong的de方fang式shi。假jia设she你ni有you一yi个ge公gong共gong内nei存cun区qu域yu,你ni不bu希xi望wang一yi个ge线xian程cheng在zai完wan成cheng一yi个ge操cao作zuo之zhi前qian另ling外wai一yi个ge线xian程cheng对dui他ta进jin行xing另ling外wai的de操cao作zuo。抛pao开kai前qian面mian所suo有you的de知zhi识shi,我wo们men可ke以yi使shi用yong这zhe样yang一yi种zhong办ban法fa,一yi种zhong所suo有you人ren都dou会hui想xiang到dao的de办ban法fa。
程cheng序xu中zhong设she置zhi一yi个ge布bu尔er类lei型xing的de公gong共gong变bian量liangFLAG,此ci公gong共gong变bian量liang唯wei一yi的de最zui用yong是shi决jue定ding线xian程cheng是shi否fou是shi否fou可ke以yi操cao作zuo公gong共gong内nei存cun区qu域yu。如ru果guo是shiTRUE则ze允yuan许xu操cao作zuo,如ru果guo是shiFALSE则ze禁jin止zhi操cao作zuo。在zai线xian程cheng将jiang要yao执zhi行xing对dui共gong享xiang内nei存cun的de操cao作zuo时shi,反fan复fu判pan断duan此ci变bian量liang,类lei似si一yi个ge死si循xun环huan,直zhi到daoFLAG变bian为weiTRUE。思si路lu很hen简jian单dan,实shi现xian起qi来lai也ye比bi前qian面mian介jie绍shao的de那na些xie方fang法fa更geng容rong易yi,在zai某mou种zhong意yi义yi上shang说shuo,它ta也ye是shi有you效xiao的de。但dan文wen章zhang前qian面mian曾zeng经jing说shuo过guo,最zui好hao不bu用yong使shi用yong这zhe种zhong方fang式shi,为wei什shen么me?回hui顾gu线xian程cheng的de工gong作zuo状zhuang态tai,我wo们men基ji本ben可ke以yi这zhe样yang划hua分fen,
1、处chu于yu可ke调tiao度du状zhuang态tai(挂gua起qi),此ci状zhuang态tai下xia的de线xian程cheng正zheng在zai等deng待daiCPU分fen配pei时shi间jian片pian给gei它ta来lai执zhi行xing自zi己ji的de操cao作zuo
2、等deng待dai状zhuang态tai,此ci时shi的de线xian程cheng我wo们men可ke以yi称cheng它ta处chu在zai不bu可ke调tiao度du状zhuang态tai,CPU绝jue不bu会hui在zai等deng待dai事shi件jian未wei发fa生sheng之zhi前qian分fen配pei时shi间jian片pian给gei它ta,例li如ru一yi个ge线xian程cheng正zheng在zai等deng待dai某mou件jian事shi情qing的de发fa生sheng,就jiu比bi如ru前qian边bian说shuo的de等deng待dai事shi件jian内nei核gai对dui象xiang的de状zhuang态tai变bian为wei已yi通tong知zhi
3、CPU已yi分fen配pei时shi间jian片pian给gei线xian程cheng,它ta正zheng在zai执zhi行xing自zi己ji的de操cao作zuo。
假jia如ru我wo们men使shi用yong事shi件jian内nei核gai对dui象xiang来lai完wan成cheng一yi些xie线xian程cheng的de同tong步bu,那na么me前qian面mian曾zeng经jing说shuo过guo,当dang等deng待dai函han数shu检jian测ce到dao事shi件jian内nei核gai对dui象xiang的de状zhuang态tai为wei未wei通tong知zhi状zhuang态tai时shi,此ci线xian程cheng将jiang处chu于yu等deng待dai状zhuang态tai,此ci时shi线xian程cheng不bu会hui使shi用yongCPU,而er如ru果guo使shi用yong前qian面mian介jie绍shao的de那na种zhong反fan复fu判pan断duan变bian量liang的de方fang法fa,那na么me此ci线xian程cheng将jiang占zhan用yongCPU资zi源yuan,这zhe很hen重chong要yao,我wo始shi终zhong认ren为wei,对dui于yu一yi个ge合he格ge的de程cheng序xu员yuan而er言yan,绝jue对dui不bu要yao无wu谓wei的de浪lang费fei客ke户hu的deCPU资zi源yuan。
虽sui然ran我wo说shuo上shang面mian那na种zhong循xun环huan判pan断duan公gong共gong状zhuang态tai位wei的de办ban法fa不bu可ke取qu,但dan它ta却que反fan映yang了le线xian程cheng同tong步bu的de思si想xiang,即ji使shi我wo们men调tiao用yong那na些xie用yong于yu同tong步bu的deAPI函han数shu,事shi实shi上shang,同tong步bu的de思si想xiang也ye是shi如ru此ci,只zhi是shi实shi现xian的de方fang法fa不bu同tong而er已yi。
信xin号hao量liang
信xin号hao量liang内nei核gai对dui象xiang用yong于yu对dui资zi源yuan进jin行xing计ji数shu。它ta们men与yu所suo有you内nei核gai对dui象xiang一yi样yang,包bao含han一yi个ge使shi用yong数shu量liang,但dan是shi它ta们men也ye包bao含han另ling外wai两liang个ge带dai符fu号hao的de32位wei值zhi,一yi个ge是shi最zui大da资zi源yuan数shu量liang,一yi个ge是shi当dang前qian资zi源yuan数shu量liang。最zui大da资zi源yuan数shu量liang用yong于yu标biao识shi信xin标biao能neng够gou控kong制zhi的de资zi源yuan的de最zui大da数shu量liang,而er当dang前qian资zi源yuan数shu量liang则ze用yong于yu标biao识shi当dang前qian可ke以yi使shi用yong的de资zi源yuan的de数shu量liang。
信xin号hao量liang的de使shi用yong规gui则ze如ru下xia:
• 如ru果guo当dang前qian资zi源yuan的de数shu量liang大da于yu0,则ze发fa出chu信xin标biao信xin号hao。
• 如ru果guo当dang前qian资zi源yuan数shu量liang是shi0,则ze不bu发fa出chu信xin标biao信xin号hao。
• 系xi统tong决jue不bu允yuan许xu当dang前qian资zi源yuan的de数shu量liang为wei负fu值zhi。
• 当dang前qian资zi源yuan数shu量liang决jue不bu能neng大da于yu最zui大da资zi源yuan数shu量liang。
创chuang建jian一yi个ge信xin号hao量liang内nei核gai对dui象xiang
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // pointer to security attributes
LONG lInitialCount, // initial count
LONG lMaximumCount, // maximum count
LPCTSTR lpName // pointer to semaphore-object name
);
和he大da多duo数shu创chuang建jian内nei核gai对dui象xiang的de函han数shu一yi样yang,它ta的de第di一yi个ge参shen数shu用yong来lai接jie受shou安an全quan信xin息xi,通tong常chang我wo们men用yongNULL来lai表biao示shi默mo认ren,最zui后hou一yi个ge参shen数shu为wei创chuang建jian这zhe个ge信xin号hao量liang的de名ming字zi,此ci名ming字zi可ke以yi使shi得de我wo们men在zai其qi他ta的de进jin程cheng中zhong使shi用yong此ci信xin号hao量liang,lInitialCount参shen数shu代dai表biao创chuang建jian信xin号hao两liang时shi允yuan许xu资zi源yuan访fang问wen的de个ge数shu,lMaximumCount用yong来lai指zhi定ding最zui大da资zi源yuan数shu,不bu要yao让ranglInitialCount大da于yulMaximumCount。
使shi用yongCreate***创chuang建jian内nei核gai对dui象xiang时shi,要yao注zhu意yi一yi个ge问wen题ti,例li如ru,如ru果guo已yi经jing有you一yi个ge进jin程chengA创chuang建jian了le一yi个ge名ming为wei'wudi_1982'的de信xin号hao量liang内nei核gai对dui象xiang,当dang另ling外wai一yi个ge进jin程chengB也ye试shi图tu创chuang建jian名ming字zi为wei'wudi_1982'的de内nei核gai对dui象xiang的de时shi候hou,系xi统tong首shou先xian要yao查cha看kan是shi否fou已yi经jing存cun在zai一yi个ge名ming字zi为wei'wudi_1982'的de内nei核gai对dui象xiang。由you于yu确que实shi存cun在zai一yi个ge带dai有you该gai名ming字zi的de对dui象xiang,因yin此ci内nei核gai要yao检jian查cha对dui象xiang的de类lei型xing。如ru果guo类lei型xing相xiang同tong(例li如ru都dou是shi信xin号hao量liang内nei核gai对dui象xiang),此ci时shi系xi统tong会hui执zhi行xing一yi次ci安an全quan检jian查cha,以yi确que定ding调tiao用yong者zhe是shi否fou拥yong有you对dui该gai对dui象xiang的de完wan整zheng的de访fang问wen权quan。如ru果guo拥yong有you这zhe种zhong访fang问wen权quan,系xi统tong就jiu在zai进jin程chengB的de句ju柄bing表biao中zhong找zhao出chu一yi个ge空kong项xiang目mu,并bing对dui该gai项xiang目mu进jin行xing初chu始shi化hua,使shi该gai项xiang目mu指zhi向xiang现xian有you的de内nei核gai对dui象xiang。如ru果guo该gai对dui象xiang类lei型xing不bu匹pi配pei,或huo者zhe调tiao用yong者zhe被bei拒ju绝jue访fang问wen,那na么meCreate****将jiang运yun行xing失shi败bai(返fan回huiNULL)。
打da开kai一yi个ge现xian有you的de信xin号hao量liang
HANDLE OpenSemaphore(
DWORD dwDesiredAccess, // access flag
BOOL bInheritHandle, // inherit flag
LPCTSTR lpName // pointer to semaphore-object name
);
参shen数shudwDesiredAccess代dai表biao了le访fang问wen权quan限xian,bInheritHandle参shen数shu表biao明ming子zi进jin程cheng是shi否fou可ke继ji承cheng,最zui后hou一yi个ge参shen数shulpName 用yong于yu指zhi明ming内nei核gai对dui象xiang的de名ming字zi。不bu能neng为wei该gai参shen数shu传chuan递diNULL,必bi须xu传chuan递di以yi0结jie尾yi的de地di址zhi。这zhe些xie函han数shu要yao搜sou索suo内nei核gai对dui象xiang的de单dan个ge名ming空kong间jian,以yi便bian找zhao出chu匹pi配pei的de空kong间jian。如ru果guo不bu存cun在zai带dai有you指zhi定ding名ming字zi的de内nei核gai对dui象xiang,该gai函han数shu返fan回huiNULL,GetLastError返fan回hui2(ERROR_FILE_NOT_FOUND)。但dan是shi,如ru果guo存cun在zai带dai有you指zhi定ding名ming字zi的de内nei核gai对dui象xiang,并bing且qie它ta是shi相xiang同tong类lei型xing的de对dui象xiang,那na么me系xi统tong就jiu要yao查cha看kan是shi否fou允yuan许xu执zhi行xing所suo需xu的de访fang问wen(通tong过guodwDesiredAccess参shen数shu进jin行xing访fang问wen)。如ru果guo拥yong有you该gai访fang问wen权quan,调tiao用yong进jin程cheng的de句ju柄bing表biao就jiu被bei更geng新xin,对dui象xiang的de使shi用yong计ji数shu被bei递di增zeng。如ru果guo为weibInheritHandle,参shen数shu传chuan递diTRUE,那na么me返fan回hui的de句ju柄bing将jiang是shi可ke继ji承cheng的de。调tiao用yongCreate*函han数shu与yu调tiao用yongOpen*函han数shu之zhi间jian的de主zhu要yao差cha别bie是shi,如ru果guo对dui象xiang并bing不bu存cun在zai,那na么meCreate*函han数shu将jiang创chuang建jian该gai对dui象xiang,而erOpen*函han数shu则ze运yun行xing失shi败bai。
通tong过guo调tiao用yongReleaseSemaphore函han数shu,线xian程cheng就jiu能neng够gou对dui信xin标biao的de当dang前qian资zi源yuan数shu量liang进jin行xing递di增zeng
BOOL ReleaseSemaphore(
HANDLE hSemaphore, // handle of the semaphore object
LONG lReleaseCount, // amount to add to current count
LPLONG lpPreviousCount // address of previous count
);
参shen数shuhSemaphore代dai表biao了le要yao操cao作zuo内nei核gai对dui象xiang的de句ju柄bing,lReleaseCount表biao明ming该gai函han数shu此ci值zhi添tian加jia给gei信xin标biao的de当dang前qian资zi源yuan数shu量liang,通tong常chang我wo们men用yong1。lpPreviousCount返fan回hui当dang前qian资zi源yuan数shu量liang的de原yuan始shi值zhi,大da多duo数shu的de时shi候hou我wo们men并bing不bu关guan心xin这zhe个ge数shu值zhi,所suo以yi一yi般ban赋fu值zhi为weiNULL。
一yi个ge例li子zi:
...{
作zuo者zhe:wudi_1982
联lian系xi方fang式shi:wudi_1982@hotmail.com
此ci代dai码ma用yong来lai演yan示shi使shi用yong信xin号hao量liang完wan成cheng线xian程cheng的de同tong步bu
转zhuan载zai请qing著zhu名ming出chu处chu
}
//主zhu要yao代dai码ma
const
SEMANAME='MySema';//信xin号hao量liang的de名ming字zi
//线xian程cheng类lei声sheng明ming
TSemaThread=class(TThread)
private
CurCount : integer;//当dang前qian计ji数shu
Flabel : TLabel;//一yi个ge用yong来lai在zai界jie面mian上shang显xian示shi当dang前qian计ji数shu的delabel
procedure GetRestult;
protected
procedure Execute;override;
public
constructor Create(Alabel : TLabel);
end;
//线xian程cheng类lei的de实shi现xian代dai码ma
constructor TSemaThread.Create(Alabel: TLabel);
begin
Flabel := Alabel;
inherited Create(False);
end;
procedure TSemaThread.Execute;
//注zhu意yi下xia面mian这zhe个ge常chang量liang的de定ding义yi
const
SEMAPHORE_ALL_ACCESS=$1F0003;
var
i : integer;
SmHandle : THandle;
begin
inherited;
CurCount := 0;
SmHandle := OpenSemaphore(SEMAPHORE_ALL_ACCESS,false,SEMANAME);
WaitForSingleObject(SmHandle,INFINITE);
for i := 0 to 10000 do
begin
Inc(CurCount);
GetRestult;
end;
ReleaseSemaphore(SmHandle,1,nil);
CloseHandle(SmHandle);
end;
//调tiao用yong此ci测ce试shi类lei的de代dai码ma
procedure TSemaThread.GetRestult;
begin
Flabel.Caption := IntToStr(CurCount);
end;
procedure TForm1.createTsClick(Sender: TObject);
begin
TSemaThread.Create(labSem);
TSemaThread.Create(labSem2);
TSemaThread.Create(labSem3);
end;
procedure TForm1.CreateSemClick(Sender: TObject);
begin
SmeHandle :=
CreateSemaphore(nil,1,3,SEMANAME);
end;
procedure TForm1.Button13Click(Sender: TObject);
begin
CloseHandle(SmeHandle)
end;
对dui上shang述shu例li子zi操cao作zuo的de说shuo明ming:
首shou先xian程cheng序xu通tong过guo一yi个ge按an钮niu来lai生sheng成cheng一yi个ge信xin号hao量liang内nei核gai对dui象xiang,当dang前qian使shi用yong计ji数shu是shi1,最zui大da为wei3,这zhe里li,如ru果guo你ni有you兴xing趣qu,你ni可ke以yi将jiang当dang前qian使shi用yong计ji数shu改gai为wei2,从cong而er你ni可ke以yi观guan察cha到dao信xin号hao量liang内nei核gai对dui象xiang和he其qi他ta内nei核gai对dui象xiang(例li如ru互hu斥chi)的de最zui大da区qu别bie。当dang信xin号hao量liang已yi经jing生sheng成cheng之zhi后hou,点dian击ji按an钮niu创chuang建jian三san个ge线xian程cheng,线xian程cheng根gen据ju信xin号hao量liang的de名ming字zi通tong过guoOpenSemaphore来lai打da开kai,这zhe样yang做zuo的de一yi个ge好hao处chu是shi,你ni可ke以yi同tong时shi多duo次ci执zhi行xing此ci程cheng序xu,例li如ru你ni将jiang这zhe个ge程cheng序xu同tong时shi打da开kai了le3个ge,在zai其qi中zhong一yi个ge中zhong,首shou先xian设she置zhi信xin号hao量liang,然ran后hou让rang其qi他ta的de程cheng序xu都dou执zhi行xing线xian程cheng操cao作zuo,你ni会hui发fa现xian,他ta们men依yi然ran同tong步bu的de很hen好hao。这zhe是shi临lin界jie区qu无wu法fa做zuo到dao的de。
对dui代dai码ma的de一yi些xie说shuo明ming:
1、多duo个ge进jin程cheng之zhi间jian来lai完wan成cheng同tong步bu。在zai前qian面mian的de例li子zi中zhong,我wo都dou是shi使shi用yong一yi个ge全quan军jun变bian量liang***:Thandle来lai记ji录lu内nei核gai对dui象xiang,以yi使shi得de我wo们men可ke以yi在zai多duo个ge线xian程cheng中zhong访fang问wen同tong一yi个ge内nei核gai对dui象xiang,这zhe里li,我wo没mei有you再zai使shi用yong这zhe个ge办ban法fa,而er是shi利li用yong了le名ming字zi,只zhi所suo以yi要yao这zhe么me做zuo,是shi因yin为wei,如ru果guo你ni给gei内nei核gai对dui象xiang起qi一yi个ge名ming字zi,那na么me你ni可ke以yi方fang便bian的de在zai其qi他ta线xian程cheng中zhong使shi用yong同tong一yi个ge内nei核gai对dui象xiang。这zhe也ye是shi使shi用yong内nei核gai对dui象xiang完wan成cheng同tong步bu和he使shi用yong临lin界jie区qu方fang式shi最zui大da的de不bu同tong,使shi用yong临lin界jie区qu,你ni只zhi能neng在zai同tong一yi个ge进jin程cheng中zhong来lai完wan成cheng同tong步bu。你ni完wan成cheng可ke以yi将jiang上shang述shu代dai码ma整zheng理li之zhi后hou做zuo成cheng一yi个ge程cheng序xu,然ran后hou同tong时shi执zhi行xing多duo个ge此ci程cheng序xu,来lai观guan察cha效xiao果guo。即ji使shi不bu再zai同tong一yi个ge进jin程cheng之zhi中zhong,线xian程cheng依yi然ran可ke以yi很hen好hao的de完wan成cheng同tong步bu。
2、Access Mask Format.在zai利li用yong名ming字zi使shi用yong内nei核gai对dui象xiang时shi,我wo们men用yong到daoOpenSemaphore来lai完wan成cheng操cao作zuo,前qian面mian说shuo了le,它ta的de第di一yi个ge参shen数shu用yong来lai决jue定ding访fang问wen权quan限xian,事shi实shi上shang,其qi他ta的de内nei核gai对dui象xiang,例li如ru互hu斥chi,他ta们men的deopen*操cao作zuo都dou是shi如ru此ci。这zhe个ge用yong来lai决jue定ding权quan限xian的de参shen数shu至zhi关guan重chong要yao,在zai上shang面mian的de代dai码ma中zhong,我wo定ding义yi了le一yi个ge常chang量liangconst SEMAPHORE_ALL_ACCESS=$1F0003;,如ru果guo你ni在zaiDLEPHI中zhong使shi用yong过guo互hu斥chi对dui象xiang来lai完wan成cheng同tong步bu,你ni会hui觉jiao得de不bu可ke理li解jie,因yin为wei在zai使shiOpenMutex函han数shu打da开kai互hu斥chi对dui象xiang时shi,第di一yi个ge参shen数shu你ni可ke以yi直zhi接jie使shi用yongMUTEX_ALL_ACCESS,那na时shi因yin为weiDELPHI的dewindows单dan元yuan中zhong存cun在zai对dui它ta的de定ding义yi,看kanMSDN的de帮bang助zhu文wen档dang,你ni会hui发fa现xian使shi用yong信xin号hao量liang时shi候hou,也ye有you一yi个ge类lei似si的de已yi经jing定ding义yi的de常chang量liangSEMAPHORE_ALL_ACCESS ,不bu过guo很hen可ke惜xi,DELPHI中zhong并bing没mei有you定ding义yi这zhe个ge常chang量liang,所suo以yi我wo们men不bu得de不bu自zi己ji定ding义yi。另ling外wai只zhi得de注zhu意yi的de一yi点dian是shi,通tong常chang情qing况kuang下xia,我wo们men都dou是shi使shi用yong$1F0003,但dan有you时shi候hou你ni不bu得de不bu使shi用yong其qi他ta的de权quan限xian信xin息xi,此ci时shi,你ni必bi须xu注zhu意yi的de一yi点dian是shi,你ni要yao让rang权quan限xian中zhong包bao含hanSEMAPHORE_MODIFY_STATE(0x0002)这zhe个ge信xin息xi,在zaiMSDN中zhong,它ta的de说shuo明ming如ru下xia,Modify state access, which is required for the ReleaseSemaphore function.你ni可ke以yi做zuo将jiang我wo上shang面mian的de代dai码ma进jin行xing简jian单dan修xiu来lai来lai测ce试shi,例li如ru你ni将jiangSEMAPHORE_ALL_ACCESS定ding义yi为weiSTANDARD_RIGHTS_REQUIRED or SYNCHRONIZE,那na么me在zai程cheng序xu执zhi行xing的de时shi候hou,你ni会hui发fa现xian只zhi有you第di一yi个ge获huo得deCPU调tiao度du的de线xian程cheng可ke以yi正zheng常chang完wan成cheng操cao作zuo,而er其qi他ta等deng待dai此ci信xin号hao量liang的de线xian程cheng将jiang永yong远yuan的de等deng待dai下xia去qu,原yuan因yin很hen简jian单dan,就jiu是shi刚gang才cai贴tie出chu的deMSDN上shang的de那na一yi句ju话hua。根gen据ju那na一yi句ju话hua,如ru果guo你ni将jiangSEMAPHORE_ALL_ACCESS 定ding义yi为wei$1F0002,你ni会hui发fa现xian,程cheng序xu也ye没mei有you问wen题ti。为wei什shen么me,这zhe就jiu要yao说shuo到daoOpenSemaphore的dedwDesiredAccess参shen数shu,那na么me你ni就jiu要yao了le解jieAccess Mask Format,可ke以yi根gen据ju下xia面mian的de图tu来lai加jia深shen理li解jie。具ju体ti参shen考kaoMSDN的de帮bang助zhu
3、内nei核gai对dui象xiang的de使shi用yong计ji数shu。在zai线xian程cheng的de执zhi行xing代dai码ma中zhong,你ni可ke以yi看kan到dao在zai线xian程cheng工gong作zuo完wan成cheng之zhi后hou的deCloseHandle(SmHandle)这zhe一yi句ju,请qing记ji住zhu,及ji时shi释shi放fang不bu必bi要yao的de资zi源yuan,是shi一yi个ge很hen好hao的de习xi惯guan。此ci时shi,你ni可ke能neng会hui问wen,我wo的de第di一yi个ge线xian程cheng调tiao用yong了leCloseHandle(SmHandle),那na么me我wo后hou边bian还huan没mei有you执zhi行xing的de线xian程cheng同tong样yang需xu要yao这zhe个ge资zi源yuan,是shi否fou就jiu不bu能neng执zhi行xing了le呢ne?答da案an是shi否fou定ding的de。内nei核gai对dui象xiang包bao含han了le一yi个ge使shi用yong计ji数shu信xin息xi,当dang你niCreate*的de时shi候hou,使shi用yong计ji数shu是shi1,随sui后hou,当dangopen*的de时shi候hou,使shi用yong计ji数shu加jia1。当dang你ni调tiao用yong了le一yi个geCloseHandle时shi,在zaiCloseHandle返fan回hui之zhi前qian,它ta会hui清qing除chu进jin程cheng的de句ju柄bing表biao中zhong的de项xiang目mu,该gai句ju柄bing现xian在zai对dui你ni的de进jin程cheng已yi经jing无wu效xiao,不bu应ying该gai试shi图tu使shi用yong它ta。无wu论lun内nei核gai对dui象xiang是shi否fou已yi经jing撤che消xiao,都dou会hui发fa生sheng清qing除chu操cao作zuo。当dang调tiao用yongCloseHandle函han数shu之zhi后hou,将jiang不bu再zai拥yong有you对dui内nei核gai对dui象xiang的de访fang问wen权quan,不bu过guo,如ru果guo该gai对dui象xiang的de使shi用yong计ji数shu没mei有you递di减jian为wei0,那na么me该gai对dui象xiang尚shang未wei被bei撤che消xiao。这zhe没mei有you问wen题ti,它ta只zhi是shi意yi味wei着zhe一yi个ge或huo多duo个ge其qi他ta进jin程cheng正zheng在zai使shi用yong该gai对dui象xiang。当dang其qi他ta进jin程cheng停ting止zhi使shi用yong该gai对dui象xiang时shi(通tong过guo调tiao用yongCloseHandle),该gai对dui象xiang将jiang被bei撤che消xiao。
一yi些xie可ke以yi用yong于yu同tong步bu的de其qi他ta内nei核gai对dui象xiang
互hu斥chi对dui象xiang
CreateMutex、ReleaseMutex、openMutex
等deng待dai计ji时shi器qi对dui象xiang
CreateWaitableTimer、SetWaitableTimer
转zhuan载zai请qing著zhu名ming出chu处chu,谢xie谢xie!
【
原文】
线程同步2
上一文中曾经介绍了线程同步的一些方法,其实完成同步还有很多很多的办法,这里最后介绍一种方式--信号量内核对象。并借此来回顾线程同步。
在谈论信号量之前,我想先谈论另外一种方式,一种你最好不要使用的方式。假设你有一个公共内存区域,你不希望一个线程在完成一个操作之前另外一个线程对他进行另外的操作。抛开前面所有的知识,我们可以使用这样一种办法,一种所有人都会想到的办法。
程序中设置一个布尔类型的公共变量FLAG,此公共变量唯一的最用是决定线程是否是否可以操作公共内存区域。如果是TRUE则允许操作,如果是FALSE则禁止操作。在线程将要执行对共享内存的操作时,反复判断此变量,类似一个死循环,直到FLAG变为TRUE。思路很简单,实现起来也比前面介绍的那些方法更容易,在某种意义上说,它也是有效的。但文章前面曾经说过,最好不用使用这种方式,为什么?回顾线程的工作状态,我们基本可以这样划分,
1、处于可调度状态(挂起),此状态下的线程正在等待CPU分配时间片给它来执行自己的操作
2、等待状态,此时的线程我们可以称它处在不可调度状态,CPU绝不会在等待事件未发生之前分配时间片给它,例如一个线程正在等待某件事情的发生,就比如前边说的等待事件内核对象的状态变为已通知
3、CPU已分配时间片给线程,它正在执行自己的操作。
假如我们使用事件内核对象来完成一些线程的同步,那么前面曾经说过,当等待函数检测到事件内核对象的状态为未通知状态时,此线程将处于等待状态,此时线程不会使用CPU,而如果使用前面介绍的那种反复判断变量的方法,那么此线程将占用CPU资源,这很重要,我始终认为,对于一个合格的程序员而言,绝对不要无谓的浪费客户的CPU资源。
虽然我说上面那种循环判断公共状态位的办法不可取,但它却反映了线程同步的思想,即使我们调用那些用于同步的API函数,事实上,同步的思想也是如此,只是实现的方法不同而已。
信号量
信号量内核对象用于对资源进行计数。它们与所有内核对象一样,包含一个使用数量,但是它们也包含另外两个带符号的32位值,一个是最大资源数量,一个是当前资源数量。最大资源数量用于标识信标能够控制的资源的最大数量,而当前资源数量则用于标识当前可以使用的资源的数量。
信号量的使用规则如下:
• 如果当前资源的数量大于0,则发出信标信号。
• 如果当前资源数量是0,则不发出信标信号。
• 系统决不允许当前资源的数量为负值。
• 当前资源数量决不能大于最大资源数量。
创建一个信号量内核对象
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // pointer to security attributes
LONG lInitialCount, // initial count
LONG lMaximumCount, // maximum count
LPCTSTR lpName // pointer to semaphore-object name
);
和大多数创建内核对象的函数一样,它的第一个参数用来接受安全信息,通常我们用NULL来表示默认,最后一个参数为创建这个信号量的名字,此名字可以使得我们在其他的进程中使用此信号量,lInitialCount参数代表创建信号两时允许资源访问的个数,lMaximumCount用来指定最大资源数,不要让lInitialCount大于lMaximumCount。
使用Create***创建内核对象时,要注意一个问题,例如,如果已经有一个进程A创建了一个名为'wudi_1982'的信号量内核对象,当另外一个进程B也试图创建名字为'wudi_1982'的内核对象的时候,系统首先要查看是否已经存在一个名字为'wudi_1982'的内核对象。由于确实存在一个带有该名字的对象,因此内核要检查对象的类型。如果类型相同(例如都是信号量内核对象),此时系统会执行一次安全检查,以确定调用者是否拥有对该对象的完整的访问权。如果拥有这种访问权,系统就在进程B的句柄表中找出一个空项目,并对该项目进行初始化,使该项目指向现有的内核对象。如果该对象类型不匹配,或者调用者被拒绝访问,那么Create****将运行失败(返回NULL)。
打开一个现有的信号量
HANDLE OpenSemaphore(
DWORD dwDesiredAccess, // access flag
BOOL bInheritHandle, // inherit flag
LPCTSTR lpName // pointer to semaphore-object name
);
参数dwDesiredAccess代表了访问权限,bInheritHandle参数表明子进程是否可继承,最后一个参数lpName 用于指明内核对象的名字。不能为该参数传递NULL,必须传递以0结尾的地址。这些函数要搜索内核对象的单个名空间,以便找出匹配的空间。如果不存在带有指定名字的内核对象,该函数返回NULL,GetLastError返回2(ERROR_FILE_NOT_FOUND)。但是,如果存在带有指定名字的内核对象,并且它是相同类型的对象,那么系统就要查看是否允许执行所需的访问(通过dwDesiredAccess参数进行访问)。如果拥有该访问权,调用进程的句柄表就被更新,对象的使用计数被递增。如果为bInheritHandle,参数传递TRUE,那么返回的句柄将是可继承的。调用Create*函数与调用Open*函数之间的主要差别是,如果对象并不存在,那么Create*函数将创建该对象,而Open*函数则运行失败。
通过调用ReleaseSemaphore函数,线程就能够对信标的当前资源数量进行递增
BOOL ReleaseSemaphore(
HANDLE hSemaphore, // handle of the semaphore object
LONG lReleaseCount, // amount to add to current count
LPLONG lpPreviousCount // address of previous count
);
参数hSemaphore代表了要操作内核对象的句柄,lReleaseCount表明该函数此值添加给信标的当前资源数量,通常我们用1。lpPreviousCount返回当前资源数量的原始值,大多数的时候我们并不关心这个数值,所以一般赋值为NULL。
一个例子:
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][/url][url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][/url]...{
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 作者:wudi_1982
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 联系方式:wudi_1982@hotmail.com
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 此代码用来演示使用信号量完成线程的同步
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif[/img][/url] 转载请著名出处
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif[/img][/url]}
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//主要代码
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]const
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SEMANAME='MySema';//信号量的名字
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] //线程类声明
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TSemaThread=class(TThread)
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] private
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CurCount : integer;//当前计数
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Flabel : TLabel;//一个用来在界面上显示当前计数的label
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] procedure GetRestult;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] protected
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] procedure Execute;override;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] public
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] constructor Create(Alabel : TLabel);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//线程类的实现代码
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]constructor TSemaThread.Create(Alabel: TLabel);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Flabel := Alabel;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inherited Create(False);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TSemaThread.Execute;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//注意下面这个常量的定义
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]const
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SEMAPHORE_ALL_ACCESS=$1F0003;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]var
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] i : integer;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SmHandle : THandle;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] inherited;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CurCount := 0;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SmHandle := OpenSemaphore(SEMAPHORE_ALL_ACCESS,false,SEMANAME);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] WaitForSingleObject(SmHandle,INFINITE);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] for i := 0 to 10000 do
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Inc(CurCount);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] GetRestult;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] ReleaseSemaphore(SmHandle,1,nil);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CloseHandle(SmHandle);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]//调用此测试类的代码
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TSemaThread.GetRestult;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] Flabel.Caption := IntToStr(CurCount);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.createTsClick(Sender: TObject);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TSemaThread.Create(labSem);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TSemaThread.Create(labSem2);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] TSemaThread.Create(labSem3);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.CreateSemClick(Sender: TObject);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] SmeHandle :=
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CreateSemaphore(nil,1,3,SEMANAME);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]procedure TForm1.Button13Click(Sender: TObject);
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]begin
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url] CloseHandle(SmeHandle)
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]end;
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/url]
对上述例子操作的说明:
首先程序通过一个按钮来生成一个信号量内核对象,当前使用计数是1,最大为3,这里,如果你有兴趣,你可以将当前使用计数改为2,从而你可以观察到信号量内核对象和其他内核对象(例如互斥)的最大区别。当信号量已经生成之后,点击按钮创建三个线程,线程根据信号量的名字通过OpenSemaphore来打开,这样做的一个好处是,你可以同时多次执行此程序,例如你将这个程序同时打开了3个,在其中一个中,首先设置信号量,然后让其他的程序都执行线程操作,你会发现,他们依然同步的很好。这是临界区无法做到的。
对代码的一些说明:
1、多个进程之间来完成同步。在前面的例子中,我都是使用一个全军变量***:Thandle来记录内核对象,以使得我们可以在多个线程中访问同一个内核对象,这里,我没有再使用这个办法,而是利用了名字,只所以要这么做,是因为,如果你给内核对象起一个名字,那么你可以方便的在其他线程中使用同一个内核对象。这也是使用内核对象完成同步和使用临界区方式最大的不同,使用临界区,你只能在同一个进程中来完成同步。你完成可以将上述代码整理之后做成一个程序,然后同时执行多个此程序,来观察效果。即使不再同一个进程之中,线程依然可以很好的完成同步。
2、Access Mask Format.在利用名字使用内核对象时,我们用到OpenSemaphore来完成操作,前面说了,它的第一个参数用来决定访问权限,事实上,其他的内核对象,例如互斥,他们的open*操作都是如此。这个用来决定权限的参数至关重要,在上面的代码中,我定义了一个常量const SEMAPHORE_ALL_ACCESS=$1F0003;,如果你在DLEPHI中使用过互斥对象来完成同步,你会觉得不可理解,因为在使OpenMutex函数打开互斥对象时,第一个参数你可以直接使用MUTEX_ALL_ACCESS,那时因为DELPHI的windows单元中存在对它的定义,看MSDN的帮助文档,你会发现使用信号量时候,也有一个类似的已经定义的常量SEMAPHORE_ALL_ACCESS ,不过很可惜,DELPHI中并没有定义这个常量,所以我们不得不自己定义。另外只得注意的一点是,通常情况下,我们都是使用$1F0003,但有时候你不得不使用其他的权限信息,此时,你必须注意的一点是,你要让权限中包含SEMAPHORE_MODIFY_STATE(0x0002)这个信息,在MSDN中,它的说明如下,Modify state access, which is required for the ReleaseSemaphore function.你可以做将我上面的代码进行简单修来来测试,例如你将SEMAPHORE_ALL_ACCESS定义为STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE,那么在程序执行的时候,你会发现只有第一个获得CPU调度的线程可以正常完成操作,而其他等待此信号量的线程将永远的等待下去,原因很简单,就是刚才贴出的MSDN上的那一句话。根据那一句话,如果你将SEMAPHORE_ALL_ACCESS 定义为$1F0002,你会发现,程序也没有问题。为什么,这就要说到OpenSemaphore的dwDesiredAccess参数,那么你就要了解Access Mask Format,可以根据下面的图来加深理解。具体参考MSDN的帮助
[url=http://www.wangchao.net.cn/bbs/hydetail_565954.html][img]http://p.blog.csdn.net/images/p_blog_csdn_net/wudi_1982/accctrl4.gif[/img][/url]
3、内核对象的使用计数。在线程的执行代码中,你可以看到在线程工作完成之后的CloseHandle(SmHandle)这一句,请记住,及时释放不必要的资源,是一个很好的习惯。此时,你可能会问,我的第一个线程调用了CloseHandle(SmHandle),那么我后边还没有执行的线程同样需要这个资源,是否就不能执行了呢?答案是否定的。内核对象包含了一个使用计数信息,当你Create*的时候,使用计数是1,随后,当open*的时候,使用计数加1。当你调用了一个CloseHandle时,在CloseHandle返回之前,它会清除进程的句柄表中的项目,该句柄现在对你的进程已经无效,不应该试图使用它。无论内核对象是否已经撤消,都会发生清除操作。当调用CloseHandle函数之后,将不再拥有对内核对象的访问权,不过,如果该对象的使用计数没有递减为0,那么该对象尚未被撤消。这没有问题,它只是意味着一个或多个其他进程正在使用该对象。当其他进程停止使用该对象时(通过调用CloseHandle),该对象将被撤消。
一些可以用于同步的其他内核对象
互斥对象
CreateMutex、ReleaseMutex、openMutex
等待计时器对象
CreateWaitableTimer、SetWaitableTimer
转载请著名出处,谢谢!