?? chap12.html
字號:
<P>{</P>
<P> criticalSection.Lock();</P>
<P> for (int x=0; x<10; ++x)</P>
<P> dstArray[x] = array[x];</P>
<P> criticalSection.Unlock();</P>
<P>}</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">現在你有機會看到線程安全類是什么樣式了,現在可以讓這個類工作了。按照以下步驟修改前面的</FONT><FONT SIZE=3>Thread</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>程序來測試</FONT><FONT SIZE=3>CCountArray</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">1.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>使用</FONT><FONT SIZE=3>File/New</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>菜單命令添加一個新的</FONT><FONT SIZE=3>C++</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>頭文件</FONT><FONT SIZE=3>CountArray.h</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,并將此頭文件加入到</FONT><FONT SIZE=3>Thread</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>工程中,并在其中添加代碼。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">2.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>再次使用</FONT><FONT SIZE=3>File/New</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>菜單命令添加一個新的</FONT><FONT SIZE=3>C++</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>資源文件</FONT><FONT SIZE=3>CountArray.cpp</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,并在其中添加代碼。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">3.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>在</FONT><FONT SIZE=3>ThreadView.cpp</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>文件中,在</FONT><FONT SIZE=3>#include "afxmt.h"</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>下面加上:</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>#include "CountArray.h"</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">4.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>在</FONT><FONT SIZE=3>ThreadView.cpp</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>文件中,刪除</FONT><FONT SIZE=3>CEvent threadStart</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>;和</FONT><FONT SIZE=3>CEvent threadEnd</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>語句,并加上下列語句:</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>CCountArray countArray;</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">5.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>從消息映射中刪除下列語句:</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>ON_MESSAGE(WM_THREADENDED, OnThreadended)</P>
<P>ON_COMMAND(ID_STOPTHREAD, OnStopthread)</P>
<P>ON_WM_CREATE()</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">6.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>用下面兩個函數更換</FONT><FONT SIZE=3>ThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數。</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>UINT WriteThreadProc(LPVOID param)</P>
<P>{</P>
<P> for(int x=0; x<10; ++x)</P>
<P> {</P>
<P> countArray.SetArray(x);</P>
<P> ::Sleep(1000);</P>
<P> }</P>
<P> return 0;</P>
<P>}</P>
<P>UINT ReadThreadProc(LPVOID param)</P>
<P>{</P>
<P> int array1[10];</P>
<P> for (int x=0; x<20; ++x)</P>
<P> {</P>
<P> countArray.GetArray(array1);</P>
<P> char str[50];</P>
<P> str[0] = 0;</P>
<P> for (int i=0; i<10; ++i)</P>
<P> {</P>
<P> int len = strlen(str);</P>
<P> wsprintf(&str[len], "%d ", array1[i]);</P>
<P> }</P>
<P> ::MessageBox((HWND)param, str, "Read Thread", MB_OK);</P>
<P> }</P>
<P> return 0;</P>
<P>}</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">7.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>用下面的語句替換</FONT><FONT SIZE=3>OnStartthread()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>中的所有語句:</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>void CThreadView::OnStartthread() </P>
<P>{</P>
<P>	// TODO: Add your command handler code here</P>
<P>	HWND hWnd = GetSafeHwnd();</P>
<P> AfxBeginThread(WriteThreadProc, hWnd);</P>
<P> AfxBeginThread(ReadThreadProc, hWnd);</P>
<P>}</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">8.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>刪除函數</FONT><FONT SIZE=3>OnStopthread()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>、</FONT><FONT SIZE=3>OnThreadended()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>、</FONT><FONT SIZE=3>OnCreate()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">9.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>在</FONT><FONT SIZE=3>ThreadView.h</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>刪除下列語句:</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>const WM_THREADENDED = WM_USER + 100;</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">10.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>在</FONT><FONT SIZE=3>ThreadView.h</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>中刪除下面的語句:</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>afx_msg void OnStopthread();</P>
<P>afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);</P>
<P>afx_msg LONG OnThreadended();</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">11.	</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>在資源編輯器中刪除“線程”主菜單中的“停止線程”菜單選項。</P>
<P ALIGN="JUSTIFY">現在編譯并運行</FONT><FONT SIZE=3>Thread</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>程序的新版本。當運行這個程序后,主窗口首先出現。選擇“線程”主菜單中的“啟動線程”菜單選項,首先彈出如圖</FONT><FONT SIZE=3>12.4</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>所示的消息框顯示當前受保護的數組的值。每次當你單擊消息框的“確定”按鈕,一個新的消息框又出現。這種消息框要出現</FONT><FONT SIZE=3>20</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>次。在消息框中列出的數組的值取決于單擊消息框的“確定”按鈕以銷毀消息框所花的時間,因為第一個線程每一秒更新一次數組中的數據。</P>
<P ALIGN="CENTER"><IMG SRC="Image441.gif" tppabs="http://166.111.167.223/computer/cai/visual_c++_5.0_programming/Image441.gif" WIDTH=96 HEIGHT=62></P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P ALIGN="CENTER">圖</FONT><FONT SIZE=1>12. 4 </FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1>讀取數據對話框</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">如果沒有線程同步,則在消息框中出現的數字將不會相同。</P>
<P ALIGN="JUSTIFY">如果仔細檢查源代碼,你會發現第一個線程</FONT><FONT SIZE=3>WriteThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>在一個循環類十次調用</FONT><FONT SIZE=3>CCountArray</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>類的成員函數</FONT><FONT SIZE=3>SetArray()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>。每一次</FONT><FONT SIZE=3>SetArray()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數將</FONT><FONT SIZE=3>criticalSection</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>給這個線程,修改受保護的數組的值,然后又釋放對</FONT><FONT SIZE=3>criticalSection</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>的所有權。注意函數</FONT><FONT SIZE=3>Sleep()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,它將這個線程掛起</FONT><FONT SIZE=3>1000</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>毫秒。</P>
<P ALIGN="JUSTIFY">第二個線程</FONT><FONT SIZE=3>ReadThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>為了構造一個顯示數組元素的字符串也在訪問</FONT><FONT SIZE=3>criticalSection</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>。但是如果</FONT><FONT SIZE=3>WriteThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>正在用更新數組中元素的值,</FONT><FONT SIZE=3>ReadThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>必須等待。反之也是對的,即</FONT><FONT SIZE=3>WriteThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>不能夠訪問受保護的數據直到它重新從</FONT><FONT SIZE=3>ReadThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>得到對</FONT><FONT SIZE=3>criticalSection</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>的所有權。</P>
<P ALIGN="JUSTIFY">如果你希望測試一下</FONT><FONT SIZE=3>criticalSection</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>是否在起作用,把</FONT><FONT SIZE=3>SetArray()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>函數最后的</FONT><FONT SIZE=3>criticalSection.Unlock()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>刪除。重新編譯并運行該程序,這次沒有消息框出現。因為</FONT><FONT SIZE=3>WriteThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>完全占有了</FONT><FONT SIZE=3>criticalSection</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,這將導致系統一致將</FONT><FONT SIZE=3>ReadThreadProc()</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>掛起,直到你退出這個程序。</P><DIR>
</FONT><FONT FACE="Arial" SIZE=3><P>(2)	</FONT><FONT FACE="黑體" LANG="ZH-CN" SIZE=3>使用</FONT><FONT FACE="Arial" SIZE=3>Mutex</FONT><FONT FACE="黑體" LANG="ZH-CN" SIZE=3>(互斥對象)</P></DIR>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">互斥對象有點象</FONT><FONT SIZE=3>critical section</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>,但有些復雜,因為它不僅允許同一程序的線程之間,而且允許不同程序的線程之間共享資源。盡管在不同程序之間的線程同步超出了本章的范圍,但是你可以通過替換</FONT><FONT SIZE=3>critical section</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>獲得使用互斥對象的經驗。</P>
<P ALIGN="JUSTIFY">下面是</FONT><FONT SIZE=3>CCountArray2</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>類的頭文件。除了名稱和互斥對象外,這個文件和原來的</FONT><FONT SIZE=3>CCountArray</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>完全相同。</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=1><P>#include "afxmt.h"</P>
<P>class CCountArray2</P>
<P>{</P>
<P>private:</P>
<P> int array[10];</P>
<P> CMutex mutex;</P>
<P>public:</P>
<P> CCountArray2() {};</P>
<P> ~CCountArray2() {};</P>
<P> void SetArray(int value);</P>
<P> void GetArray(int dstArray[10]);</P>
<P>};</P>
</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">下面是</FONT><FONT SIZE=3>CCountArray2</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>的執行文件,正如你所看到的,盡管互斥對象和</FONT><FONT SIZE=3>critical section</FONT><FONT FACE="宋體" LANG="ZH-CN" SIZE=3>提供相同的服務,但是二者使用起來還是有很多不同的。</P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -