⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch27.htm

📁 VC使用所有细节的逻列
💻 HTM
📖 第 1 页 / 共 5 页
字号:
but only to a point. That is, semaphores allow a maximum number of threads to access a resource simultaneously.</P>

<P>When you create the semaphore, you tell it how many threads should be allowed simultaneous access to the resource. Then, each time a thread grabs the resource, the semaphore decrements its internal counter. When the counter reaches 0, no further 
threads are allowed access to the guarded resource until another thread releases the resource, which increments the semaphore's counter.</P>

<P>You create a semaphore by supplying the initial count and the maximum count, like this:</P>

<pre><font color="#008000">CSemaphore Semaphore(2, 2);</font></pre>

<P>Because, in this section, you'll be using a semaphore to create a thread-safe class, it's actually more convenient to declare a <font color="#008000">CSemaphore</font> pointer as a data member of the class and then create the <font 
color="#008000">CSemaphore</font> object dynamically in the class's constructor, like this:</P>

<pre><font color="#008000">semaphore = new CSemaphore(2, 2);</font></pre>

<P>You should do this because you have to initialize a data member in the constructor rather than at the time you declare it. With the critical-section and mutex objects, you didn't have to supply arguments to the class's constructors, so you were able to 
create the object at the same time you declared it.</P>

<P>Once you have the semaphore object created, it's ready to start counting resource access. To implement the counting process, you first create a <font color="#008000">CSingleLock</font> (or <font color="#008000">CMultiLock</font>, if you're dealing with 
multiple thread-synchronization objects) object, giving it a pointer to the semaphore you want to use, like this:</P>

<pre><font color="#008000">CSingleLock singleLock(semaphore);</font></pre>

<P>Then, to decrement the semaphore's count, you call the <font color="#008000">CSingleLock</font> object's <font color="#008000">Lock()</font> member function:</P>

<pre><font color="#008000">singleLock.Lock();</font></pre>

<P>At this point, the semaphore object has decremented its internal counter. This new count remains in effect until the semaphore object is released, which you can do explicitly by calling the object's <font color="#008000">Unlock()</font> member 
function:</P>

<pre><font color="#008000">singleLock.Unlock();</font></pre>

<P>Alternatively, if you've created the <font color="#008000">CSingleLock</font> object locally on the stack, you can just let the object go out of scope, which not only automatically deletes the object but also releases the hold on the semaphore. In 
other words, both calling <font color="#008000">Unlock()</font> and deleting the <font color="#008000">CSingleLock</font> object increments the semaphore's counter, enabling a waiting thread to access the guarded resource.</P>

<P>Listing 27.11 is the header file for a class called <font color="#008000">CSomeResource</font>. <font color="#008000">CSomeResource</font> is a mostly useless class whose only calling is to demonstrate the usage of semaphores. The class has a single 
data member, which is a pointer to a <font color="#008000">CSemaphore</font> object. The class also has a constructor and destructor, as well as a member function called <font color="#008000">UseResource()</font>, which is where the semaphore will be 
used.</P>

<P><I>Listing 27.11&#151;SOMERESOURCE.H</I></P>

<pre><font color="#008000">#include &quot;afxmt.h&quot;</font></pre>

<pre><font color="#008000">class CSomeResource</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">private:</font></pre>

<pre><font color="#008000">    CSemaphore* semaphore;</font></pre>

<pre><font color="#008000">public:</font></pre>

<pre><font color="#008000">    CSomeResource();</font></pre>

<pre><font color="#008000">    ~CSomeResource();</font></pre>

<pre><font color="#008000">    void UseResource();</font></pre>

<pre><font color="#008000">};</font></pre>

<P>Listing 27.12 shows the <font color="#008000">CSomeResource</font> class's implementation file. You can see that the <font color="#008000">CSemaphore</font> object is constructed dynamically in the class's constructor and deleted in the destructor. The 
<font color="#008000">UseResource()</font> member function simulates accessing a resource by attaining a count on the semaphore and then sleeping for five seconds, after which the hold on the semaphore is released when the function exits and the <font 
color="#008000">CSingleLock</font> object goes out of scope.</P>

<P><I>Listing 27.12&#151;SOMERESOURCE.CPP</I></P>

<pre><font color="#008000">#include &quot;stdafx.h&quot;</font></pre>

<pre><font color="#008000">#include &quot;SomeResource.h&quot;</font></pre>

<pre><font color="#008000">CSomeResource::CSomeResource()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    semaphore = new CSemaphore(2, 2);</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">CSomeResource::~CSomeResource()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    delete semaphore;</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">void CSomeResource::UseResource()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    CSingleLock singleLock(semaphore);</font></pre>

<pre><font color="#008000">    singleLock.Lock();</font></pre>

<pre><font color="#008000">    Sleep(5000);</font></pre>

<pre><font color="#008000">}</font></pre>

<P>If you modify the Thread application to use the <font color="#008000">CSomeResource</font> object, you can watch semaphores at work. Follow these steps:</P>

<ol>

<li><P> Delete any CountArray files that are still in the project.</P>

<li><P> Create the new empty SomeResource.h and SomeResource.cpp files in the project.</P>

<li><P> Add the code from Listings 27.11 and 27.12 to these empty files.</P>

<li><P> Load ThreadView.cpp and replace the line <font color="#008000">#include </font><font color="#008000">&quot;CountArray2.h&quot;</font> with the following:</P>

<pre><font color="#008000">#include &quot;SomeResource.h&quot;</font></pre>

<li><P> Replace the line <font color="#008000">CCountArray2 countArray</font> with the following:</P>

<pre><font color="#008000">CSomeResource someResource;</font></pre>

<li><P> Replace the <font color="#008000">WriteThreadProc()</font> and <font color="#008000">ReadThreadProc()</font> functions with the functions shown in Listing 27.13.</P>

<P><I>Listing 27.13&#151;ThreadProc1(), ThreadPrco2() and ThreadProc3()</I></P>

<pre><font color="#008000">UINT ThreadProc1(LPVOID param)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    someResource.UseResource();</font></pre>

<pre><font color="#008000">    ::MessageBox((HWND)param,</font></pre>

<pre><font color="#008000">        &quot;Thread 1 had access.&quot;, &quot;Thread 1&quot;, MB_OK);</font></pre>

<pre><font color="#008000">    return 0;</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">UINT ThreadProc2(LPVOID param)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    someResource.UseResource();</font></pre>

<pre><font color="#008000">    ::MessageBox((HWND)param,</font></pre>

<pre><font color="#008000">        &quot;Thread 2 had access.&quot;, &quot;Thread 2&quot;, MB_OK);</font></pre>

<pre><font color="#008000">    return 0;</font></pre>

<pre><font color="#008000">}</font></pre>

<pre><font color="#008000">UINT ThreadProc3(LPVOID param)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">    someResource.UseResource();</font></pre>

<pre><font color="#008000">    ::MessageBox((HWND)param,</font></pre>

<pre><font color="#008000">        &quot;Thread 3 had access.&quot;, &quot;Thread 3&quot;, MB_OK);</font></pre>

<pre><font color="#008000">    return 0;</font></pre>

<pre><font color="#008000">}</font></pre>

<li><P> Replace the code in the <font color="#008000">OnStartthread()</font> function with that shown in Listing 27.14.</P>

<P><I>Listing 27.14&#151;LST27_14.TXT&#151;New Code for the </I>OnStartthread()<I> Function</I></P>

<pre><font color="#008000">    HWND hWnd = GetSafeHwnd();</font></pre>

<pre><font color="#008000">    AfxBeginThread(ThreadProc1, hWnd);</font></pre>

<pre><font color="#008000">    AfxBeginThread(ThreadProc2, hWnd);</font></pre>

<pre><font color="#008000">    AfxBeginThread(ThreadProc3, hWnd);</font></pre>

</ol>

<P>Now compile and run the new version of the Thread application. When the main window appears, select the <U>T</U>hread, <U>S</U>tart Thread command. In about five seconds, two message boxes will appear informing you that Thread one and Thread two had 
access to the guarded resource. About five seconds after that, a third message box will appear, telling you that Thread three also had access to the resource. Thread three took five seconds longer because Thread one and Thread two grabbed control of the 
resource first. The semaphore is set to allow only two simultaneous resource accesses, so Thread three had to wait for Thread one or Thread two to release its hold on the semaphore.</P>

<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">

<P>Although the sample programs in this chapter have demonstrated using a single thread-synchronization object, you can have as many synchronization objects as you need in a single program. You can even use critical sections, mutexes, and semaphores all 
at once in order to protect different data sets and resources in different ways.</P>

<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>

<H3><B>From Here...</B></H3>

<P>For complex applications, threads offer the ability to keep data processing moving along fast and efficiently. You no longer have to wait for one part of the program to finish its task before moving on to something else. For example, a spreadsheet 
application could use one thread to update the calculations while the main thread continues accepting entries from the user. Using threads, however, leads to some interesting problems, not the least of which is the need to control access to shared 
resources. Writing a threaded application requires some thought and careful consideration of how the threads will be used and what resources they'll access.</P>

<P>For more information on related topics, please refer to the following chapters:</P>

<ul>

<li> <A HREF="index04.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index04.htm" target="text">Chapter 4</A>, &quot;Messages and Commands,&quot; can give you some review on how MFC applications process Windows messages with message maps.</P>

<li> <A HREF="index24.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index24.htm" target="text">Chapter 24</A>, &quot;Improving Your Application's Performance,&quot; offers a number of techniques for writing faster and more robust programs.</P>

</ul>

<p><hr></p>

<center>

<p><font size=-2>

&copy; 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a

Simon and Schuster Company.</font></p>

</center>

</BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -