標籤:情況 pac close 讀取 int windows平台 oid ftps struct
眾所周知,windows平台上實現線程同步。或者說資源的加鎖與解鎖的方法有核心事件、臨界區、相互排斥量、訊號量,甚至interlocked系列函數等多種手段。
可是在日常的編程中,我們使用這些手段對 “多個線程同一時候對同一個資源進行讀寫”的時候,在讀寫之前先要對資源假鎖,讀寫完之後要對資源解鎖。
設想這樣一種情況,有一個ftpserver。每天有非常頻繁的對這個ftp服務的檔案進行下載,可是差點兒好幾天才會對這些檔案進行更新。在我們每一次對檔案下載的時候,讀取檔案的時候都要對檔案進行加鎖,以保證同一時候沒有其它人對檔案進行寫入。
可是這些加鎖的行為。在99%的時候都是不會有人同一時候寫入檔案的。僅僅有1%的情況下會有人同一時候也要寫入檔案。這種話,我們多鎖就大大的浪費了,並且你在加鎖的同一時候,別人即使也僅僅是讀取檔案,也須要等你先解鎖。
解決問題的辦法是,對檔案的讀取設定共用鎖定。多個線程能夠同一時候讀檔案。不會互相堵塞。再設定獨佔鎖,當要對檔案進行寫入的時候。加上獨佔鎖,這樣別的線程此時不能讀也不能寫。
windows提供了一個稱為slim 的共用/獨佔鎖來解決問題。可是呢。slim僅僅在vista和window server 2008才支援。在之前的版本號碼上沒有支援。
於是,我就w利用現有的線程同步手段,來類比達到slim這一個共用/獨佔鎖的功能,代碼封裝例如以下:
</pre><pre name="code" class="cpp">//共用和獨佔鎖(讀不鎖。寫鎖),適用於資源的讀的頻率比寫的頻率高的情況//共用鎖定: 大家都能夠同一時候讀,可是不能寫。//獨佔鎖: 就是僅僅有一個人獨佔使用,無論是讀還是寫//規定:acquire和release必須成對出現。不支援嵌套以及互相嵌套//缺點:須要對加鎖過程本身進行臨界區控制。會帶來細微的效能損失#ifdef __cplusplusextern "C" {#endifstruct SELock //Shared & Exclusive lock{ RTL_CRITICAL_SECTION sec_shared,sec_exclusive; //對加鎖代碼本身進行臨界區控制 HANDLE exclusive_evt; HANDLE shared_evt; volatile long shared_count;};//初始化一個SE鎖_inline void InitializeSELock(SELock *lock){ InitializeCriticalSection(&lock->sec_shared); InitializeCriticalSection(&lock->sec_exclusive); lock->exclusive_evt = CreateEventW(NULL,TRUE,TRUE,NULL); lock->shared_evt = CreateEventW(NULL,TRUE,TRUE,NULL); lock->shared_count = 0;}//清理一個SE鎖_inline void DeleteSELock(SELock *lock){ DeleteCriticalSection(&lock->sec_shared); DeleteCriticalSection(&lock->sec_exclusive); CloseHandle(lock->exclusive_evt); CloseHandle(lock->shared_evt); lock->shared_count = 0;}//請求共用鎖定,用於讀_inline void AcquireSELockShared(SELock *lock){ EnterCriticalSection(&lock->sec_exclusive); EnterCriticalSection(&lock->sec_shared); WaitForSingleObject(lock->exclusive_evt,INFINITE); //等待獨佔鎖 ++lock->shared_count; if(lock->shared_count) ResetEvent(lock->shared_evt); //開啟共用鎖定 LeaveCriticalSection(&lock->sec_shared); LeaveCriticalSection(&lock->sec_exclusive);}//釋放共用鎖定_inline void ReleaseSELockShared(SELock *lock){ EnterCriticalSection(&lock->sec_shared); --lock->shared_count; if(!lock->shared_count) SetEvent(lock->shared_evt); //關閉共用鎖定 LeaveCriticalSection(&lock->sec_shared); }//請求獨佔鎖_inline void AcquireSELockExclusive(SELock *lock){ EnterCriticalSection(&lock->sec_exclusive); WaitForSingleObject(lock->exclusive_evt,INFINITE); //等待獨佔鎖 WaitForSingleObject(lock->shared_evt,INFINITE); //等待共用鎖定 ResetEvent(lock->exclusive_evt); //開啟獨佔鎖 LeaveCriticalSection(&lock->sec_exclusive);}//釋放獨佔鎖_inline void ReleaseSELockExclusive(SELock *lock){ SetEvent(lock->exclusive_evt); //關閉獨佔鎖}#ifdef __cplusplus}#endif
基於windows api實現的共用鎖定/獨佔鎖