学习视频链接
03进程的创建_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1Fd4y1G7Td?p=3&vd_source=0471cde1c644648fafd07b54e303c905
目录
一、创建线程
二、线程间同步
2.1 线程不同步的结果
2.2 原子操作上锁
2.3 临界区
2.4 内核对象
三、线程间通信
四、进程的创建
五、进程间通信
5.1 通信方式分类
5.2 共享内存的写法
一、创建线程
#include <iostream>
#include <windows.h>using namespace std;// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{int i = 0;while (i < 10) {Sleep(200);i++;printf("SubThread: %d\n", i);}return 0;
}int main()
{//CreateThread(NULL, 0, ThreadProc, 0, 0, 0); // 创建,不开启线程HANDLE h = CreateThread(NULL, 0, ThreadProc, 0, CREATE_SUSPENDED, 0); // 创建,开启线程int i = 10;while (i < 20) {Sleep(200);i++;printf("ParentThread: %d\n", i);}ResumeThread(h); // 开启线程Sleep(3000);return 0;
}
h 代表句柄

如果关闭两次线程就需要开启两次线程

二、线程间同步
2.1 线程不同步的结果
#include <iostream>
#include <windows.h>using namespace std;int g = 0;// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{for (int i = 0; i < 1000000; i++) {g++;}return 0;
}int main()
{HANDLE h = CreateThread(NULL, 0, ThreadProc, 0, 0, 0);for (int i = 0; i < 1000000; i++) {g++;}WaitForSingleObject(h, INFINITE); // 无限等待printf("%d\n", g);CloseHandle(h); // 关闭线程return 0;
}
子线程和主线程可能同时写主线程,导致不能够达到预期的 2000000

2.2 原子操作上锁
#include <iostream>
#include <windows.h>using namespace std;unsigned int g = 0;// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{for (int i = 0; i < 1000000; i++) {InterlockedIncrement(&g);}return 0;
}int main()
{HANDLE h = CreateThread(NULL, 0, ThreadProc, 0, 0, 0);for (int i = 0; i < 1000000; i++) {InterlockedIncrement(&g);}WaitForSingleObject(h, INFINITE); // 无限等待printf("%d\n", g);CloseHandle(h); // 关闭线程return 0;
}
2.3 临界区
#include <iostream>
#include <windows.h>using namespace std;int g = 0;
CRITICAL_SECTION g_sec; // 创建临界区对象// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{for (int i = 0; i < 100000; i++) {EnterCriticalSection(&g_sec); // 进入临界区g++;LeaveCriticalSection(&g_sec);}return 0;
}int main()
{// 初始化临界区对象InitializeCriticalSection(&g_sec);HANDLE h = CreateThread(0, 0, ThreadProc, 0, 0, 0);for (int i = 0; i < 100000; i++) {EnterCriticalSection(&g_sec);g++;LeaveCriticalSection(&g_sec);}WaitForSingleObject(h, INFINITE); // 无限等待线程执行完printf("%d\n", g);// 句柄释放CloseHandle(h);return 0;
}
2.4 内核对象
1、内核对象
每一个内核对象在任何时候都处于两种状态之一:信号态和无信号态
线程在等待其中的一个或多个内核对象时,如果在等待的一个或多个内核对象处于无信号态,线程自身将被系统挂起,直到等待的内核对象变为有信号状态时,线程才恢复运行。常用的等待函数有 2 个
2、等待线程函数
在多线程下面,有时候我们会希望等待某一线程完成了再继续做其他事情,要实现这个目的,可以使用 Windows API 函数 WaitForSingleObject,或者 WaitForMultipleObjects。这两个函数都会等待 Object 被标为有信号时才返回的。这两个函数的优点是它们在等待的过程中会进入一个非常高效沉睡状态,只占用极少的 CPU 时间片
(1) 信号
#include <iostream>
#include <windows.h>using namespace std;int g = 0;
HANDLE hmutex;// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{for (int i = 0; i < 100000; i++) {WaitForSingleObject(hmutex, INFINITE); // hmutex 有信号->无信号g++;ReleaseMutex(hmutex); // hmutex 无信号->有信号}return 0;
}int main()
{// 创建内核对象hmutex = CreateMutex(NULL, FALSE, NULL); // hmutex 创建->有信号HANDLE h = CreateThread(NULL, 0, ThreadProc, 0, 0, 0);for (int i = 0; i < 100000; i++) {WaitForSingleObject(hmutex, INFINITE); // hmutex 有信号->无信号g++;ReleaseMutex(hmutex); // hmutex 无信号->有信号}WaitForSingleObject(h, INFINITE); // 无限等待线程执行完printf("%d\n", g);// 释放内核释放CloseHandle(h);CloseHandle(hmutex);return 0;
}
(2) 事件
#include <iostream>
#include <windows.h>using namespace std;int g = 0;
HANDLE hEvent;// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{for (int i = 0; i < 100000; i++) {WaitForSingleObject(hEvent, INFINITE); // hmutex 有事件->无事件g++;SetEvent(hEvent); // hmutex 无事件->有事件}return 0;
}int main()
{// 创建事件对象hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);HANDLE h = CreateThread(NULL, 0, ThreadProc, 0, 0, 0);for (int i = 0; i < 100000; i++) {WaitForSingleObject(hEvent, INFINITE); // hmutex 有事件->无事件g++;SetEvent(hEvent); // hmutex 无事件->有事件}WaitForSingleObject(h, INFINITE); // 无限等待线程执行完printf("%d\n", g);// 释放内核释放CloseHandle(h);CloseHandle(hEvent);return 0;
}
三、线程间通信
1、使用全局变量进行通信
2、参数传递方式
#include <iostream>
#include <windows.h>using namespace std;struct node {int age;int id;
};int g = 0;
HANDLE hEvent;// 回调函数
DWORD WINAPI ThreadProc(PVOID lp)
{node n = *(node*)lp;cout << n.age << " " << n.id << endl;;for (int i = 0; i < 100000; i++) {WaitForSingleObject(hEvent, INFINITE); // hmutex 有事件->无事件g++;SetEvent(hEvent); // hmutex 无事件->有事件}return 0;
}int main()
{node n;n.id = 1;n.age = 10;// 创建事件对象hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);HANDLE h = CreateThread(NULL, 0, ThreadProc, &n, 0, 0);for (int i = 0; i < 100000; i++) {WaitForSingleObject(hEvent, INFINITE); // hmutex 有事件->无事件g++;SetEvent(hEvent); // hmutex 无事件->有事件}WaitForSingleObject(h, INFINITE); // 无限等待线程执行完printf("%d\n", g);// 释放内核释放CloseHandle(h);CloseHandle(hEvent);return 0;
}

3、消息传递方式
MFC 里面的
四、进程的创建
#include <iostream>
#include <windows.h>using namespace std;int main()
{TCHAR commandLine[] = TEXT("C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe www.baidu.com");_STARTUPINFOW startInfo = { sizeof(_STARTUPINFOW)};_PROCESS_INFORMATION processInfo;/*BOOL CreateProcess( LPCTSTR lpApplicationName, 应用程序名称 LPTSTR lpCommandLine, 命令行字符串 LPSECURITY_ATTRIBUTES lpProcessAttributes, 进程的安全属性 LPSECURITY_ATTRIBUTES lpThreadAttributes, 线程的安全属性 BOOL bInheritHandles, 是否继承父进程的属性 DWORD dwCreationFlags, 创建标志 LPVOID lpEnvironment, 指向新的环境块(环境变量)的指针 LPCTSTR lpCurrentDirectory, 指向当前目录名的指针 LPSTARTUPINFO lpStartupInfo, 传递给新进程的信息 LPPROCESS_INFORMATION lpProcessInformation 新进程返回的信息 );*/bool ret = CreateProcess(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &startInfo, &processInfo);if (ret == false) {cout << "创建进程失败" << endl;return 0;}else {WaitForSingleObject(processInfo.hProcess, INFINITE);cout << "新创建的进程ID: " << processInfo.dwProcessId << endl;cout << "新创建的线程ID: " << processInfo.dwThreadId << endl;CloseHandle(processInfo.hProcess);CloseHandle(processInfo.hThread);}return 0;
}
上述代码就完成了打开浏览器进程的任务了

五、进程间通信
5.1 通信方式分类

>套接字(socket):
套接字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
5.2 共享内存的写法
输出字符的程序
#include <iostream>
#include <windows.h>using namespace std;int main()
{/*HANDLE CreateFileMapping(HANDLE hFile, // 物理文件句柄LPSECURITY_ATTRIBUTES lpAttributes, // 安全设置DWORD flProtect, // 保护设置DWORD dwMaximumSizeHigh, // 高位文件大小DWORD dwMaximumSizeLow, // 低位文件大小LPCTSTR lpName // 共享内存名称);*/// 创建共享文件句柄HANDLE hMapFile = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, 1024, TEXT("fileMap"));char *buf = (char*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024);gets_s(buf, 100);while (1) {Sleep(1000);}UnmapViewOfFile(buf);CloseHandle(hMapFile);return 0;
}
接收字符的程序
#include <iostream>
#include <windows.h>using namespace std;int main()
{/*HANDLE CreateFileMapping(HANDLE hFile, // 物理文件句柄LPSECURITY_ATTRIBUTES lpAttributes, // 安全设置DWORD flProtect, // 保护设置DWORD dwMaximumSizeHigh, // 高位文件大小DWORD dwMaximumSizeLow, // 低位文件大小LPCTSTR lpName // 共享内存名称);*/// 创建共享文件句柄HANDLE hMapFile = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, 1024, TEXT("fileMap"));char *buf = (char*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024);cout << buf << endl;getchar();UnmapViewOfFile(buf);CloseHandle(hMapFile);return 0;
}


















