OS:Windows
一、基础知识
1.Window 可以选择的线程库有3种
AfxBeginThread是MFC的全局函数,是对CreateThread的封装。
CreateThread是Win32 API函数,AfxBeginThread最终要调到CreateThread。
而_beginthread是C的运行库函数。
2.CreateThread
当使用CreateProcess调用时,系统将创建一个进程和一个主线程。CreateThread将在主线程的基础上创建一个新线程,大致做如下步骤:
(1)在内核对象中分配一个线程标识/句柄,可供管理,由CreateThread返回
(2)把线程退出码置为STILL_ACTIVE,把线程挂起计数置1
(3)分配context结构
(4)分配两页的物理存储以准备栈,保护页设置为PAGE_READWRITE,第2页设为PAGE_GUARD
(5)lpStartAddr和lpvThread值被放在栈顶,使它们成为传送给StartOfThread的参数
(6)把context结构的栈指针指向栈顶(第5步)指令指针指向startOfThread函数
c++手工多核运行代码
首先把数组分成N段,然后创建N个线程,每个线程独自计算1段数据
MYDATA:
struct MYDATA {
int begin, end;
int* A, * B, * C;
int P, N;
};
单独的运算线程
DWORD ThreadProc(LPVOID IpParam) {
MYDATA* pmd = (MYDATA*)IpParam;
int* A = pmd->A, * B = pmd->B, * C = pmd->C;
int begin = pmd->begin, end = pmd->end, P = pmd->P, N = pmd->N;
TRACE("执行时间total = %d ms, I am Thread %d\n", begin, end);
CString sTip;
while (1)
{
}
return 0;
}
把static MYDATA mydt[m]拆分成M段,然后调用M个线程进行计算
//multi thread test
SYSTEM_INFO info;
GetSystemInfo(&info);
//线程数量
const int NTHREADS = 1;
HANDLE hThread[NTHREADS];
//传入线程的参数,存放每个线程的分段起、止index
static MYDATA thread_args[NTHREADS];
//将长度为nSize的列表进行分段, temp就是平均到每个线程的计算元素
int temp = (nSize) / NTHREADS;
//计算每个线程要处理的起、止位置,存入mydt[]
for (int i = 0; i < NTHREADS; ++i) {
thread_args[i].begin = i * temp, thread_args[i].end = i * temp + temp;
if (i == NTHREADS - 1) // 最后一个线程计算剩余的
thread_args[i].end = nSize;
//创建线程开始计算
hThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, &thread_args[i], 0, NULL);
}
//等待所有线程结束
WaitForMultipleObjects(NTHREADS, hThread, TRUE, INFINITE);
SetThreadAffinityMask windows下线程指定CPU核心
实用的函数来获取当前CPU的核心数量
OS:Windows 10
CPU:Intel Core i5-10400
SYSTEM_INFO info;
GetSystemInfo(&info);
printf("Number of processors: %d.\n", info.dwNumberOfProcessors);
output
&info 0x002adc70 {dwOemId=0 wProcessorArchitecture=0 wReserved=0 ...} _SYSTEM_INFO *
dwOemId 0 unsigned long
wProcessorArchitecture 0 unsigned short
wReserved 0 unsigned short
dwPageSize 4096 unsigned long
lpMinimumApplicationAddress 0x00010000 void *
lpMaximumApplicationAddress 0x7ffeffff void *
dwActiveProcessorMask 4095 unsigned long
dwNumberOfProcessors 12 unsigned long
dwProcessorType 586 unsigned long
dwAllocationGranularity 65536 unsigned long
wProcessorLevel 6 unsigned short
wProcessorRevision 42243 unsigned short
子线程如何访问主线程的全局变量
主进程的全局变量对它的所有子线程都是有效的
1.创建子线程时,将主线程指针作为参数.
2.在子线程函数中,通过AfxGetApp()获得主线程指针.
一、主进程的全局变量对它的所有子线程都是有效的
二、你可通过__beginthread(FuncName,0,pData) 传递给子线程你要访问的变量
其中 FuncName 为子线程函数的名称,pData为一个你要指向的传递的变量的指针
要子线程能看到主线程的全局变量的声明就可以了。
如不在同一文件,可在子线程的.cpp 文件里声明
extern int g_var;
如果在同一个主线程里创多个子线程,恐怕不宜直接调用吧?
1.结构struct 包含class传递参数到子线程
struct threadInfo
{
CDC * dc; //画布
int nOffset; //偏移量
COLORREF clrRGB; //颜色
};
see:https://blog.csdn.net/cbNotes/article/details/8277180
2.CreateThread(...)传入多个参数
传递class作为参数到子线程
例子:
class CThreadParam
{
public:
IVMManager *m_pVMManager1;
CString m_strExtNum;
//要多少参数就有多少参数
};
CThreadParam *pParam = new CThreadParam;
pParam-> m_pVMManager1=...;
...
DWORD dwThreadId;
CreateThread( NULL,0,ThreadFunc,pParam,0,&dwThreadId);
DWORD WINAPI CConnectDlg::ThreadFunc( LPVOID lpParam )
{
//运行线程
//强制指针类型转换
(CThreadParam*)pMyParam = (CThreadParam*)lpParam;
//
//pMyParam-> m_pVMManager1
//pMyParam-> m_strExtNum
}