生活随笔
收集整理的這篇文章主要介紹了
秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在《秒殺多線程第十一篇讀者寫者問題》文章中我們使用事件和一個記錄讀者個數的變量來解決讀者寫者問題。問題雖然得到了解決,但代碼有點復雜。本篇將介紹一種新方法——讀寫鎖SRWLock來解決這一問題。讀寫鎖在對資源進行保護的同時,還能區分想要讀取資源值的線程(讀取者線程)和想要更新資源的線程(寫入者線程)。對于讀取者線程,讀寫鎖會允許他們并發的執行。當有寫入者線程在占有資源時,讀寫鎖會讓其它寫入者線程和讀取者線程等待。因此用讀寫鎖來解決讀者寫者問題會使代碼非常清晰和簡潔。
?
??? 下面就來看看如何使用讀寫鎖,要注意編譯讀寫鎖程序需要VS2008,運行讀寫鎖程序要在Vista或Windows Server2008系統(比這兩個更高級的系統也可以)。讀寫鎖的主要函數就五個,分為初始化函數,寫入者線程申請和釋放函數,讀取者線程申請和釋放函數,以下是詳細的函數使用說明:
第一個?InitializeSRWLock
函數功能:初始化讀寫鎖
函數原型:VOID?InitializeSRWLock(PSRWLOCK?SRWLock);
函數說明:初始化(沒有刪除或銷毀SRWLOCK的函數,系統會自動清理)
?
第二個?AcquireSRWLockExclusive
函數功能:寫入者線程申請寫資源。
函數原型:VOID?AcquireSRWLockExclusive(PSRWLOCK?SRWLock);
?
第三個?ReleaseSRWLockExclusive
函數功能:寫入者線程寫資源完畢,釋放對資源的占用。
函數原型:VOID?ReleaseSRWLockExclusive(PSRWLOCK?SRWLock);
?
第四個?AcquireSRWLockShared
函數功能:讀取者線程申請讀資源。
函數原型:VOID?AcquireSRWLockShared(PSRWLOCK?SRWLock);
?
第五個?ReleaseSRWLockShared
函數功能:讀取者線程結束讀取資源,釋放對資源的占用。
函數原型:VOID?ReleaseSRWLockShared(PSRWLOCK?SRWLock);
?
注意一個線程僅能鎖定資源一次,不能多次鎖定資源。
?
使用讀寫鎖精簡后的代碼如下(代碼中變參函數的實現請參閱《C,C++中使用可變參數》,控制臺顏色設置請參閱《VC 控制臺顏色設置》):
[cpp]?view plaincopy
?? #include?<stdio.h>?? #include?<process.h>?? #include?<windows.h>?? ?? BOOL?SetConsoleColor(WORD?wAttributes)?? {?? ????HANDLE?hConsole?=?GetStdHandle(STD_OUTPUT_HANDLE);?? ????if?(hConsole?==?INVALID_HANDLE_VALUE)?? ????????return?FALSE;?? ????return?SetConsoleTextAttribute(hConsole,?wAttributes);?? }?? const?int?READER_NUM?=?5;???? ?? CRITICAL_SECTION?g_cs;?? SRWLOCK??????????g_srwLock;??? ?? void?ReaderPrintf(char?*pszFormat,?...)?? {?? ????va_list???pArgList;?? ????va_start(pArgList,?pszFormat);?? ????EnterCriticalSection(&g_cs);?? ????vfprintf(stdout,?pszFormat,?pArgList);?? ????LeaveCriticalSection(&g_cs);?? ????va_end(pArgList);?? }?? ?? unsigned?int?__stdcall?ReaderThreadFun(PVOID?pM)?? {?? ????ReaderPrintf("?????編號為%d的讀者進入等待中...\n",?GetCurrentThreadId());?? ?????? ????AcquireSRWLockShared(&g_srwLock);?? ?? ?????? ????ReaderPrintf("編號為%d的讀者開始讀取文件...\n",?GetCurrentThreadId());?? ????Sleep(rand()?%?100);?? ????ReaderPrintf("?編號為%d的讀者結束讀取文件\n",?GetCurrentThreadId());?? ?? ?????? ????ReleaseSRWLockShared(&g_srwLock);?? ????return?0;?? }?? ?? void?WriterPrintf(char?*pszStr)?? {?? ????EnterCriticalSection(&g_cs);?? ????SetConsoleColor(FOREGROUND_GREEN);?? ????printf("?????%s\n",?pszStr);?? ????SetConsoleColor(FOREGROUND_RED?|?FOREGROUND_GREEN?|?FOREGROUND_BLUE);?? ????LeaveCriticalSection(&g_cs);?? }?? ?? unsigned?int?__stdcall?WriterThreadFun(PVOID?pM)?? {?? ????WriterPrintf("寫者線程進入等待中...");?? ?????? ????AcquireSRWLockExclusive(&g_srwLock);?? ?????????? ?????? ????WriterPrintf("??寫者開始寫文件.....");?? ????Sleep(rand()?%?100);?? ????WriterPrintf("??寫者結束寫文件");?? ?? ?????? ????ReleaseSRWLockExclusive(&g_srwLock);?? ????return?0;?? }?? int?main()?? {?? ????printf("??讀者寫者問題繼?讀寫鎖SRWLock\n");?? ????printf("?--?by?MoreWindows(?http://blog.csdn.net/MoreWindows?)?--\n\n");?? ?? ?????? ????InitializeCriticalSection(&g_cs);?? ????InitializeSRWLock(&g_srwLock);?? ?? ????HANDLE?hThread[READER_NUM?+?1];?? ????int?i;?? ?????? ????for?(i?=?1;?i?<=?2;?i++)?? ????????hThread[i]?=?(HANDLE)_beginthreadex(NULL,?0,?ReaderThreadFun,?NULL,?0,?NULL);?? ?????? ????hThread[0]?=?(HANDLE)_beginthreadex(NULL,?0,?WriterThreadFun,?NULL,?0,?NULL);?? ????Sleep(50);?? ?????? ????for?(?;?i?<=?READER_NUM;?i++)?? ????????hThread[i]?=?(HANDLE)_beginthreadex(NULL,?0,?ReaderThreadFun,?NULL,?0,?NULL);?? ????WaitForMultipleObjects(READER_NUM?+?1,?hThread,?TRUE,?INFINITE);?? ????for?(i?=?0;?i?<?READER_NUM?+?1;?i++)?? ????????CloseHandle(hThread[i]);?? ?? ?????? ????DeleteCriticalSection(&g_cs);?? ????return?0;?? }??
對比下《秒殺多線程第十一篇讀者寫者問題》中的代碼就可以發現這份代碼確實清爽許多了。這個程序用VS2008編譯可以通過,但在XP系統下運行會導致報錯。
在Win7系統下能夠正確的運行,結果如圖所示:
?
?
最后總結一下讀寫鎖SRWLock
1.讀寫鎖聲明后要初始化,但不用銷毀,系統會自動清理讀寫鎖。
2.讀取者和寫入者分別調用不同的申請函數和釋放函數。
?
?
轉載請標明出處,原文地址:http://blog.csdn.net/morewindows/article/details/7650574
如果覺得本文對您有幫助,請點擊‘頂’支持一下,您的支持是我寫作最大的動力,謝謝。
總結
以上是生活随笔為你收集整理的秒杀多线程第十四篇 读者写者问题继 读写锁SRWLock的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。