Windows核心编程系列文章仅作为实验报告和Windows编程学习参考,不作为任何技术文章,还望大佬们勿喷。
1. 实验名称
线程编程
2. 实验环境
- VC6.0++
- Windows 7
3. 实验目的
- 掌握线程的概念、线程的创建,终止函数
- 掌握线程管理,优先级设置
- 掌握线程同步技术,包括线程用户模式下同步,例如临界区(关键段)线程同步,以及采用内核对象模式线程同步,例如事件,互斥量,信号量
- 要求能够应用线程相关函数完成多线程编程,并完成多线程同步
4. 实验内容、步骤及结果
1. 实验内容
- 程序创建两个线程,一个主线程,主线程创建一个附加线程,采用事件实现线程同步:
- (1). 附加线程功能为:在一个字符串中查找一个单词,若找到了该单词,通知主线程把找到的单词显示出来;
- (2). 若附加线程退出时,还未查找到此单词,则通知主线程,打印出未找到此单词。
- 编写一个程序,有四个线程1、2、3、4。采用互斥量,或者其他线程同步技术,实现线程同步。
- 线程1的功能就是输出1,线程2的功能就是输出2,以此类推………现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
- A:1 2 3 4 1 2….
- B:2 3 4 1 2 3….
- C:3 4 1 2 3 4….
- D:4 1 2 3 4 1….
2. 实验步骤
- 创建两个线程,一个主线程和一个附加线程
#include <windows.h>
#include <iostream>
#include <process.h>
#include <string>
using namespace std;
string szStr = "This is second experience in windows programming.";
string szUserChar;
HANDLE hThread;
int flag = -1;
DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
int i = (int)lpParam;
cout << "来自主线程 : " << i << endl;
cout << "\n请出入想要查找的单词:\n";
cin >> szUserChar;
flag = szStr.find(szUserChar);
if (flag != -1)
{
return 0;
}
else
{
flag = -1;
return 0;
}
}
int main(int argc, char argv[])
{
DWORD dwThreadID; //创建附加线程
DWORD dwExitCode;
cout << "主线程的字符串为: " << szStr << endl;
cout << "\n创建附加线程\n";
cout << "Loading......\n\n";
hThread = CreateThread(NULL, 0, ThreadFunc, (LPVOID)11, 0, &dwThreadID);
WaitForSingleObject(hThread, INFINITE); //等待线程结束
cout << "\n返回主线程\n";
if(::GetExitCodeThread(hThread, &dwExitCode)) //判断线程是否结束运行
{
if(dwExitCode == STILL_ACTIVE)
{
cout << "\n线程还在运行中\n";
}
else
{
if (flag == -1)
{
cout << "附加线程退出,没有找到该单词" << endl;
}
else
{
cout << "附加线程退出,找到单词:" << szUserChar << endl;
}
}
}
cout << endl;
return 0;
}
- 编写一个程序,有四个线程。
- 这里只给出主函数内容
int main(int argc, char *argv)
{
DWORD dwThreadID;
HANDLE h[4];
hFileA = CreateFile(TEXT("A.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //创建 A B C D 4个文件
hFileB = CreateFile(TEXT("B.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
hFileC = CreateFile(TEXT("C.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
hFileD = CreateFile(TEXT("D.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(hFileA);
CloseHandle(hFileB);
CloseHandle(hFileC);
CloseHandle(hFileD);
printf("%s\n", FileName[0]);
printf("%s\n", FileName[1]);
printf("%s\n", FileName[2]);
printf("%s\n", FileName[3]);
g_hMain = CreateSemaphore(NULL, 0, 1, NULL); //初始化信号量和关键段
g_hThreadParameter1 = CreateSemaphore(NULL, 0, 1, NULL); //当前1个资源,最大允许1个同时访问
g_hThreadParameter2 = CreateSemaphore(NULL, 0, 1, NULL); //当前0个资源,最大允许1个同时访问
g_hThreadParameter3 = CreateSemaphore(NULL, 0, 1, NULL); //当前0个资源,最大允许1个同时访问
g_hThreadParameter4 = CreateSemaphore(NULL, 0, 1, NULL); //当前0个资源,最大允许1个同时访问
InitializeCriticalSection(&g_csThreadCode);
h[0] = CreateThread(NULL, NULL, Thread1, NULL, 0, &dwThreadID);
h[1] = CreateThread(NULL, NULL, Thread2, NULL, 0, &dwThreadID);
h[2] = CreateThread(NULL, NULL, Thread3, NULL, 0, &dwThreadID);
h[3] = CreateThread(NULL, NULL, Thread4, NULL, 0, &dwThreadID);
ReleaseSemaphore(g_hMain, 1, NULL); //信号量++
WaitForMultipleObjects(4, h, TRUE, INFINITE); //等待线程结束
DeleteCriticalSection(&g_csThreadCode); //销毁信号量和关键段
CloseHandle(g_hThreadParameter1);
CloseHandle(g_hThreadParameter2);
CloseHandle(g_hThreadParameter3);
CloseHandle(g_hThreadParameter4);
CloseHandle(h[0]);
CloseHandle(h[1]);
CloseHandle(h[2]);
CloseHandle(h[3]);
return 0;
}
3. 实验结果(实验运行截图)
- 创建一个主线程和一个附加线程
- 查找字符成功
线程退出时仍然没有查到字符
- 编写一个程序,有四个线程。
- 代码执行成功。
A.txt:
B.txt:
C.txt:
D.txt:
5. 实验中的问题及心得
- 学会了线程编程,了解了线程的创建,以及终止。
- 在第二个实验中由于线程需要等待信号量,前一个信号量来唤醒下一个信号量,而第一个线程并没有信号量可以唤醒,所以需要在第一个线程之前加一个主函数的信号量,用来触发第一个线程函数。
- 掌握了线程编程中同步技术,特别是对于事件,互斥量,信号量的理解以及编程中的使用,如果事件,互斥量,信号量不能使用得当就会造成线程运行混乱或者数据不同步或者造成死锁等问题。
6. 附件
以下是实验代码