?? win32 multithreading and synchronization.html
字號(hào):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Win32 Multithreading and Synchronization (ver. 1.0.0)</title>
<meta http-equiv="Content-Type" content="text/html charset=utf-8" />
<meta content="Copyright 2002 SpiderMan" name="Copyright" />
<meta content="SpiderMan" name="Author" />
<meta content="English" name="Language" />
<style type="text/css">
<!--
body {font: 12px Verdana, Arial, Helvetica, sans-serif}
p {text-align: left;}
p.para {text-indent: 12px}
table.example {width: 450px; font-size: 12px}
span.function {color: gray; font-weight: bold}
span.term {color: gray; font-style: italic}
div.lastupdate {text-align: right}
/* hack so IE will center my stuff since it doesn't recognize margin: auto */
div.center {text-align: center}
a:link {text-decoration: underline; color: #003F7F}
a:visited {text-decoration: underline; color: #003F7F}
a:hover {text-decoration: underline; color: #CC0000}
h2, h3 {font-size: 12px}
h1.title {font-weight: normal; text-align: center; font-size: 12px}
pre.example {background-color: #EBEBEB; border: 1px solid #000000; padding: 3px; text-align: left; width: 570px; margin-left: auto; margin-right: auto}
-->
</style>
</head>
<body>
<h1 class="title">
<strong>Win32 Multithreading and Synchronization (ver. 1.0.0)</strong>
<br/>
by: <a href="mailto:spiderman@witty.com">SpiderMan</A> of <a href="http://blacksun.box.sk">Black Sun Research Facility </a>
</h1>
<h2>Table of Contents:</h2>
<ul>
<li><a href="#intro" title="Click to skip down to this section.">Introduction</a></li>
<li><a href="#background" title="Click to skip down to this section.">Background</a></li>
<li><a href="#multi" title="Click to skip down to this section.">Multithreading</a></li>
<li><a href="#synch" title="Click to skip down to this section.">Synchronization</a></li>
<ul>
<li><a href="#mutex" title="Click to skip down to this section.">Mutexes</a></li>
<li><a href="#sema" title="Click to skip down to this section.">Semaphores</a></li>
<li><a href="#cs" title="Click to skip down to this section.">Critical Sections</a></li>
<li><a href="#events" title="Click to skip down to this section.">Events</a></li>
</ul>
<li><a href="#ref" title="Click to skip down to this section.">References</a></li>
<li><a href="#con" title="Click to skip down to this section.">Conclusion</a></li>
</ul>
<a name="intro">
<h2>Introduction:</h2>
<p class="para">
This tutorial will explain how to create and manage multiple threads in Windows. This is an advanced tutorial; the reader should be familiar with Win32 programming.
</p>
<p class="para">
The need for responsive user-centric programs is a good reason to create programs that use multiple threads. By creating multiple threads, a program can seem to do many things at once (on a computer with more than one CPU, the program actually will do many things at once). For example, a word processor could have one thread that handles the painting of the processor's window while another thread saves the document being typed every few minutes while yet another thread actively monitors the document for spelling errors all without forcing the user to wait while each task is completed.
</p>
<a name="background">
<h2>Background:</h2>
<p class="para">
On a single CPU Windows machine, all threads are kept track of and given a slice of processor time (usually a few milliseconds). Windows will cycle through the list it keeps, pausing and resuming each thread. Once a thread has used up its time on the processor, Windows will pause the thread, record its CPU registers (along with some other data), and, after restoring all its data, activate the next thread. Each thread has two priorities: base and dynamic. The base priority can be changed, however, it cannot be changed to have a priority higher than that of the parent thread. Dynamic priority is the same as the base priority, however, it can be raised or lowered by Windows. Windows chooses which thread to run next based on the thread's dynamic priority. Naturally, threads with a higher dynamic priority run first.
</p>
<a name="multi">
<h2>Multithreading:</h2>
<p class="para">
Initially, every program gets one thread, known as the primary thread, which is created by the Windows Object Manager. The primary thread can be used to create child threads. To create another thread call <span class="function">CreateThread</span>. <span class="function">CreateThread</span> takes the following parameters:
</p>
<div class="center">
<pre class="example">
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // access privileges
DWORD dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier
);
</pre>
</div>
<p>
If the first parameter is passed as NULL, the thread will get the default security descriptor. The second parameter allows you to set the initial stack size, you can pass 0 to give the thread the default stack size. The third parameter is a pointer to the function the thread should start executing. The fourth parameter holds any arguments you want to pass to the function. You can pass either a 0 or CREATE_SUSPENDED to the fifth parameter. If it is 0, the thread starts running as soon as it is created. If the value is CREATE_SUSPENDED, the thread will be created suspended and will not start running until you call <span class="function">ResumeThread</span>. The last parameter is a pointer to a DWORD which will hold the unique ID of the thread, after it is created.
</p>
<p class="para">
If a thread was created with the CREATE_SUSPENDED flag, you will want to call <span class="function">ResumeThread</span> to start using it. <span class="function">ResumeThread</span> takes the following parameter:
</p>
<div class="center">
<pre class="example">
DWORD ResumeThread(HANDLE hThread);
</pre>
</div>
<p>
hThread is the handle received by <span class="function">CreateThread</span>. To suspend the thread again, call <span class="function">SuspendThread</span>:
</p>
<div class="center">
<pre class="example">
DWORD SuspendThread(HANDLE hThread);
</pre>
</div>
<p>
Once again, hThread is the handle received by <span class="function">CreateThread</span>.
</p>
<p class="para">
While a thread is suspended, you may want to raise its base priority and then wake it again. A thread with a higher priority will get more processor time. To change a thread's base priority, call <span class="function">SetThreadPriority</span>:
</p>
<div class="center">
<pre class="example">
BOOL SetThreadPriority(
HANDLE hThread, // handle to the thread
int nPriority // thread priority level
);
</pre>
</div>
<p>
nPriority can be one of seven values:
</p>
<div class="center">
<table class="example" border="1" cellspacing="0" cellpadding="2" summary="Table of possible values for thread priorities">
<tr>
<td>THREAD_PRIORITY_LOWEST</td>
<td>Two levels below process</td>
</tr>
<tr>
<td>THREAD_PRIORITY_BELOW_NORMAL</td>
<td>One level below process</td>
</tr>
<tr>
<td>THREAD_PRIORITY_NORMAL</td>
<td>Normal priority</td>
</tr>
<tr>
<td>THREAD_PRIORITY_ABOVE_NORMAL</td>
<td>One level above process</td>
</tr>
<tr>
<td>THREAD_PRIORITY_HIGHEST</td>
<td>Two levels above process</td>
</tr>
<tr>
<td>THREAD_PRIORITY_TIME_CRITICAL</td>
<td>Priority of 15</td>
</tr>
<tr>
<td>THREAD_PRIORITY_IDLE</td>
<td>Priority of 1</td>
</tr>
</table>
</div>
<p>
To retrieve a thread's base priority level, call <span class="function">GetThreadPriority</span>:
</p>
<div class="center">
<pre class="example">
int GetThreadPriority(HANDLE hThread);
</pre>
</div>
<p class="para">
After you are done using a thread, you may want to terminate it. To do this, call <span class="function">ExitThread</span>. <span class="function">ExitThread</span> followed by a <span class="function">CloseHandle</span> is the graceful way to shut down a thread. To immediately stop a thread, call <span class="function">TerminateThread</span>. The specs of each function are:
</p>
<div class="center">
<pre class="example">
VOID ExitThread( DWORD dwExitCode);
</pre>
</div>
<div class="center">
<pre class="example">
BOOL CloseHandle(HANDLE hThread);
</pre>
</div>
<div class="center">
<pre class="example">
BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode);
</pre>
</div>
<p>
Windows automatically calls <span class="function">ExitThread</span> when a thread ends its function. dwExitCode is the exit code you want to pass. The exit code can later be retrieved using <span class="function">GetExitCodeThread</span>:
</p>
<div class="center">
<pre class="example">
BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode // pointer to a DWORD to hold the exit code
);
</pre>
</div>
<p class="para">
The following is an example of how to use threads.
</p>
<div class="center">
<pre class="example">
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
DWORD ThreadID;
HANDLE TName;
void ExampleFunction()
{
for(int x=0; x<10; x++)
{
std:cout<<"Doing important stuff!\n";
}
}
void main()
{
TName= CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)ExampleFunction,
NULL, CREATE_SUSPENDED, &ThreadID);
if (TName == NULL)
{
std::cout<<"Could not create thread!\n";
return false;
}
if (!SetThreadPriority(TName, THREAD_PRIORITY_BELOW_NORMAL))
{
std::cout<<"SetThreadPriority failed!\n";
return false;
}
if ((ResumeThread(TName)) == -1)
{
std::cout<<"ResumeThread failed!\n";
return false;
}
WaitForSingleObject(TName, INFINITE); // discussed later
CloseHandle(TName);
}
</pre>
</div>
<a name="synch">
<h2>Synchronization:</h2>
<p class="para">
Picture this: a word processor program creates two threads, one to read a file and another to write to a file. Everything is fine at first, the first thread waits for the second to finish writing to the file before reading it. The two threads work happily, everything is fine as long as the writing thread always writes first. But one dark day, the reading thread reads the file before the writing thread writes to the file and the program fails. This is known as a <span class="term">race condition</span> because both threads race to finish their file operation. The program will always fail if the reading thread wins the race. A <span class="term">race condition</span> is the result of bad synchronization. Another problem is the dreaded <span class="term">deadlock</span>. In a <span class="term">deadlock</span>, both threads will wait for each other to finish but neither thread will finish until the other finishes first, causing them to become locked. The solution to this problem is to use one, or more, of the synchronization objects provided by Windows.
</p>
<p class="para">
To gain ownership of any of the synchronization objects, a thread can use <span class="function">WaitForSingleObject</span>, <span class="function">WaitForSingleObjectEx</span>, <span class="function">WaitForMultipleObjects</span>, or <span class="function">WaitForMultipleObjectsEx</span>.
</p>
<p class="para">
<span class="function">WaitForSingleObject</span> allows a thread to suspend itself while it waits for ownership of one of the synchronization objects.
</p>
<div class="center">
<pre class="example">
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
</pre>
</div>
<p>
The second parameter is the amount of time, in milliseconds, the thread is willing to wait for the object before it returns. If the second parameter is set to INFINITE, the function will not time-out. If the second parameter is set to 0, the function will try to gain ownership of the object and return immediately, even if it didn't gain ownership.
</p>
<p class="para">
<span class="function">WaitForSingleObjectEx</span> is the same as <span class="function">WaitForSingleObject</span> except, it adds one more option: alert if I/O operation completes.
</p>
<div class="center">
<pre class="example">
DWORD WaitForSingleObjectEx(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds, // time-out interval
BOOL bAlertable // alertable option
);
</pre>
</div>
<p>
If the last parameter is set to true, the function will return when an asynchronous I/O operation completes.
</p>
<p class="para">
<span class="function">WaitForMultipleObjects</span> allows a thread to wait for multiple synchronization objects at once. It can be set to return when any or all of the objects become available.
</p>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -