上一節中,是單獨的把線程函數和主函數放到了一起,不太符合類的封裝。這一節把多線程放到一個類裏面,然後在主函數中調用這個類以及多線程。多線程,需要定義爲靜態成員函數,如果裏面涉及到參數,也應該定義爲靜態成員變量。
頭文件, *.h
#include <Windows.h>
#include <iostream>
using namespace std;
class Test
{
public:
Test();
~Test();
static int add(int b);
static DWORD WINAPI thread1(LPVOID lpParameter);
static DWORD WINAPI thread2(LPVOID lpParameter);
private:
static int a;
static int c;
};
static CRITICAL_SECTION th1, th2;
源文件, *.cpp
#include "StaticThread.h"
int Test::a = 10; // 靜態成員變量,需要這樣進行初始化
int Test::c = 10;
Test::Test()
{
InitializeCriticalSection(&th1); // 用線程鎖之前,一定要初始化
InitializeCriticalSection(&th2);
}
Test::~Test()
{
DeleteCriticalSection(&th1); // 用完以後,要釋放
DeleteCriticalSection(&th2);
}
int Test::add(int b) // 形參
{
return a + b;
}
DWORD WINAPI Test::thread1(LPVOID lpParameter)
{
while(true)
{
EnterCriticalSection(&th1);
if (a < 50)
{
Sleep(1);// 交出權限,讓下一個線程執行
cout << "thread1: a = " << a++ << endl;
}
else
break;
LeaveCriticalSection(&th1);
}
return 0;
}
DWORD WINAPI Test::thread2(LPVOID lpParameter)
{
while(true)
{
EnterCriticalSection(&th2);
if (c < 50)
{
Sleep(1);// 交出權限,讓上一個線程執行
cout << "thread2: c = " << c++ << endl;
}
else
break;
LeaveCriticalSection(&th2);
}
return 0;
}
主文件, main.cpp
#include<iostream>
using namespace std;
int main()
{
Test t;
HANDLE ht_1, ht_2;
ht_1 = CreateThread(NULL, 0, t.thread1, NULL, 0, NULL);// 需要注意,調用多線程的方式
ht_2 = CreateThread(NULL, 0, t.thread2, NULL, 0, NULL);
CloseHandle(ht_1);
CloseHandle(ht_2);
Sleep(300);// 讓主函數等待線程運行完
cout << "main thread" << endl;
system("pause");
return 0;
}
運行結果如下: 可以看到,開頭輸出的 1線程,被2線程打斷了,導致 a 沒有完全輸出,就開始輸出 c。之後的話就比較均勻了。
線程中Sleep(1), 主要是爲了讓線程停止一下,把控制權交出去。上面代碼例子中,是對兩個變量,分別在各自線程中,在各自的CPU核上運行,所以互不干擾。
運行多次,發現,這種輸出,是不太可控的,有時候a先輸出,有時候,輸出到一半,被停下。
推測,是CPU分配任務比較智能(或者隨機)導致的。