我在网上找到了这个关于多线程和下载代码的教程,以便在 Visual Studio 2010 上试用。http://www.codeproject.com/Articles/14746/Multithreading-Tutorial
我在下面复制的与“线程本地存储”相关的程序之一供您参考。它看起来很简单,因为 2 个线程,都增加了类数据成员 'm1'、'm2'、'm3'。在这个例子中,'m2' 是一个静态类变量,两个线程都可以访问。
请注意,在代码中,临界区在文件开头使用“#define WITH_SYNCHRONIZATION”启用。我的理解是,由于 'TMain()' 中的 'for 循环' 受临界区保护,因此首先到达 'TMain()' 的线程将完成 50,000 增量作为一个整体,而不会与另一个线程交错,打印输出'50,020 for m2',另一个线程将继续其余部分并稍后打印出'100,020 for m2'。
但是不,m2 的打印结果看起来根本没有关键部分。'm2' 值使用以下值打乱:
螺纹 t2: ... m2=50376 ...
螺纹 t1: ... m2=63964 ...
我一定错过了一些基本的东西。它是什么?
以下代码来自网页,数值变化不大,可以在 VStudio 中轻松编译。
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <string>
using namespace std;
#define WITH_SYNCHRONIZATION
class ThreadX
{
private:
int m1;
static int m2; // shared variable
static __declspec(thread) int m3; // thread local variable
#ifdef WITH_SYNCHRONIZATION
CRITICAL_SECTION m_CriticalSection;
#endif
public:
string threadName;
ThreadX()
{
m1 = 10;
#ifdef WITH_SYNCHRONIZATION
InitializeCriticalSection(&m_CriticalSection);
#endif
}
virtual ~ThreadX()
{
#ifdef WITH_SYNCHRONIZATION
// Release resources used by the critical section object.
DeleteCriticalSection(&m_CriticalSection);
#endif
}
void TMain(void)
{
#ifdef WITH_SYNCHRONIZATION
EnterCriticalSection( &m_CriticalSection );
#endif
for ( int i = 1; i <= 50000; i++ )
{
++m1; // init value 10
++m2; // init value 20
++m3; // init value 30
}
printf( "Thread %s: m1 = %d, m2 = %d, m3 = %d\n", threadName.c_str(), m1, m2, m3 );
#ifdef WITH_SYNCHRONIZATION
LeaveCriticalSection( &m_CriticalSection );
#endif
}
static unsigned __stdcall ThreadStaticTMain(void * pThis)
{
ThreadX * pthX = (ThreadX*)pThis;
pthX->TMain();
return 1;
}
};
int ThreadX::m2 = 20;
int ThreadX::m3 = 30;
int main()
{
// In this program we create 2 threads and request that their
// entry-point-function be the TMain() function of the ThreadX
// class. Because _beginthreadex() cannot accept a class member
// function we must employ a 2 step process involving a tricky
// cast to accomplish this.
ThreadX * o1 = new ThreadX();
HANDLE hth1;
unsigned uiThread1ID;
hth1 = (HANDLE)_beginthreadex( NULL,
0,
ThreadX::ThreadStaticTMain,
o1,
CREATE_SUSPENDED,
&uiThread1ID );
if ( hth1 == 0 )
printf("Failed to create thread 1\n");
DWORD dwExitCode;
GetExitCodeThread( hth1, &dwExitCode );
printf( "initial thread 1 exit code = %u\n", dwExitCode );
o1->threadName = "t1";
ThreadX * o2 = new ThreadX();
HANDLE hth2;
unsigned uiThread2ID;
hth2 = (HANDLE)_beginthreadex( NULL,
0,
ThreadX::ThreadStaticTMain,
o2,
CREATE_SUSPENDED,
&uiThread2ID );
if ( hth2 == 0 )
printf("Failed to create thread 2\n");
GetExitCodeThread( hth2, &dwExitCode );
printf( "initial thread 2 exit code = %u\n", dwExitCode );
o2->threadName = "t2";
ResumeThread( hth1 );
ResumeThread( hth2 );
WaitForSingleObject( hth1, INFINITE );
WaitForSingleObject( hth2, INFINITE );
GetExitCodeThread( hth1, &dwExitCode );
printf( "thread 1 exited with code %u\n", dwExitCode );
GetExitCodeThread( hth2, &dwExitCode );
printf( "thread 2 exited with code %u\n", dwExitCode );
// The handle returned by _beginthreadex() has to be closed
// by the caller of _beginthreadex().
CloseHandle( hth1 );
CloseHandle( hth2 );
delete o1;
o1 = NULL;
delete o2;
o2 = NULL;
printf("Primary thread terminating.\n");
return 0;
}