C++开发基础之CreateThread详细用法

基础知识

CreateThread

CreateThread是一个Windows API函数,用于创建一个新的线程。

函数原型如下:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  __drv_aliasesMem LPVOID lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);

参数说明:

  • lpThreadAttributes:一个指向 SECURITY_ATTRIBUTES 结构体的指针,指定了新的线程对象的安全特性。如果为NULL,则新的线程对象不能被继承。
  • dwStackSize:指定新线程的堆栈大小。如果为0,则使用默认堆栈大小。
  • lpStartAddress:一个指向线程函数的指针,表示新线程的入口点。
  • lpParameter:传递给线程函数的参数。
  • dwCreationFlags:指定了线程创建的标志位。可以为以下值之一或它们的组合:
    • 0:线程立即启动并运行。
    • CREATE_SUSPENDED:线程被创建挂起,不立即运行。
  • lpThreadId:一个指向 DWORD 变量的指针,接收新线程的 ID。

返回值:

如果函数调用成功,则返回一个指向新创建的线程对象的句柄;否则返回NULL。

使用CreateThread函数可以创建一个新的线程对象,并将其运行在独立的执行上下文中。在调用CreateThread函数后,新线程将开始运行指定的线程函数,并且可以访问该函数中的参数。

CreateSemaphore

CreateSemaphore是一个Windows API函数,用于创建一个新的命名或未命名的信号量对象。它可以被用于控制多个线程对共享资源的访问。

函数原型如下:

HANDLE CreateSemaphore(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  LONG                  lInitialCount,
  LONG                  lMaximumCount,
  LPCSTR                lpName
);

参数说明:

  • lpSemaphoreAttributes:一个指向 SECURITY_ATTRIBUTES 结构体的指针,指定了新的信号量对象的安全特性。如果为NULL,则新的信号量对象不能被继承。
  • lInitialCount:指定了信号量对象的初始计数器值。如果为0,则所有等待该信号量的线程都将进入等待状态。
  • lMaximumCount:指定了信号量对象的最大计数器值。它必须大于0。
  • lpName:指定了信号量对象的名称。如果为NULL,则创建未命名的信号量对象。

返回值:

如果函数调用成功,则返回一个指向新创建的信号量对象的句柄;否则返回NULL。

使用CreateSemaphore函数可以创建一个信号量对象,然后使用WaitForSingleObject或WaitForMultipleObjects函数等待信号量对象。当信号量对象计数器为0时,线程将进入等待状态,直到有另一个线程释放该信号量。使用ReleaseSemaphore函数可以增加信号量对象的计数器,并唤醒等待该信号量的线程。

GetThreadAffinityMask和SetThreadAffinityMask

GetThreadAffinityMask和SetThreadAffinityMask是Windows API提供的两个函数,用于获取和设置线程的亲和性掩码。这些函数可以用来查询和修改线程在处理器上运行的位置。

  1. GetThreadAffinityMask函数:

    • 函数原型:BOOL GetThreadAffinityMask(HANDLE hThread, PDWORD_PTR lpProcessAffinityMask, PDWORD_PTR lpSystemAffinityMask)
    • 作用:获取指定线程的亲和性掩码信息。
    • 参数:
      • hThread:线程句柄,指定要查询亲和性的线程。
      • lpProcessAffinityMask:指向DWORD_PTR类型的变量的指针,用于接收进程的亲和性掩码。
      • lpSystemAffinityMask:指向DWORD_PTR类型的变量的指针,用于接收系统的亲和性掩码。
    • 返回值:如果函数成功执行,返回非零值;如果函数执行失败,返回零。
  2. SetThreadAffinityMask函数:

    • 函数原型:DWORD_PTR SetThreadAffinityMask(HANDLE hThread, DWORD_PTR dwThreadAffinityMask)
    • 作用:将指定线程绑定到指定的处理器核心。
    • 参数:
      • hThread:线程句柄,指定要设置亲和性的线程。
      • dwThreadAffinityMask:DWORD_PTR类型的值,指定线程的亲和性掩码。
    • 返回值:如果函数成功执行,返回之前的线程亲和性掩码;如果函数执行失败,返回0。

GetThreadAffinityMask函数用于查询指定线程的亲和性掩码信息。通过传递线程句柄以及两个指向变量的指针,可以获取该线程所绑定的处理器核心范围。lpProcessAffinityMask接收进程的亲和性掩码,lpSystemAffinityMask接收系统的亲和性掩码。这些掩码是一个位图,在位图中的每一位代表一个处理器核心,为1表示该核心可用,为0表示不可用。

SetThreadAffinityMask函数用于设置指定线程的亲和性掩码,以将线程绑定到特定的处理器核心。通过传递线程句柄和线程亲和性掩码,可以将线程限制在指定的处理器核心上运行。该函数返回之前的线程亲和性掩码,可以用来还原之前的设置。

请注意,修改线程的亲和性可能需要管理员权限,并且需要谨慎使用。不正确的使用可能导致性能问题或系统稳定性问题。

示例代码

使用Windows API提供的CreateThread函数来创建线程。下面是一个使用CreateThread函数创建线程的示例代码:

#include <iostream>
#include <windows.h>

// 全局变量
HANDLE semaphore;
DWORD_PTR affinityMask;

// 线程函数
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
    // 获取线程ID
    DWORD threadId = GetCurrentThreadId();

    // 获取线程的处理器亲和性
    DWORD_PTR oldAffinityMask;
    if (!GetThreadAffinityMask(GetCurrentThread(), &oldAffinityMask, &affinityMask))
    {
        std::cerr << "Failed to get thread affinity mask. Error: " << GetLastError() << std::endl;
        return 1;
    }

    std::cout << "Thread " << threadId << " started. Affinity Mask: " << affinityMask << std::endl;

    // 等待信号量
    WaitForSingleObject(semaphore, INFINITE);

    // 执行一些工作...

    std::cout << "Thread " << threadId << " finished." << std::endl;

    // 恢复线程的处理器亲和性
    if (!SetThreadAffinityMask(GetCurrentThread(), oldAffinityMask))
    {
        std::cerr << "Failed to set thread affinity mask. Error: " << GetLastError() << std::endl;
        return 1;
    }

    return 0;
}

int main()
{
    // 创建信号量
    semaphore = CreateSemaphore(NULL, 0, 1, NULL);
    if (semaphore == NULL)
    {
        std::cerr << "Failed to create semaphore. Error: " << GetLastError() << std::endl;
        return 1;
    }

    // 启动线程
    HANDLE thread = CreateThread(NULL, 0, MyThreadFunction, NULL, 0, NULL);
    if (thread == NULL)
    {
        std::cerr << "Failed to create thread. Error: " << GetLastError() << std::endl;
        return 1;
    }

    // 设置线程的处理器亲和性
    affinityMask = 1; // 将线程绑定到第一个处理器
    if (!SetThreadAffinityMask(thread, affinityMask))
    {
        std::cerr << "Failed to set thread affinity mask. Error: " << GetLastError() << std::endl;
        return 1;
    }

    std::cout << "Thread started. Affinity Mask: " << affinityMask << std::endl;

    // 发送信号量以启动线程
    ReleaseSemaphore(semaphore, 1, NULL);

    // 等待线程结束
    WaitForSingleObject(thread, INFINITE);

    // 关闭句柄
    CloseHandle(thread);
    CloseHandle(semaphore);

    return 0;
}

在上面的示例中,我们首先创建了一个信号量 semaphore,然后使用 CreateThread 创建了一个新的线程,并将线程函数设置为 MyThreadFunction。在主线程中,我们使用 SetThreadAffinityMask 将线程绑定到第一个处理器,并发送信号量以启动线程。

在线程函数 MyThreadFunction 中,我们首先获取当前线程的 ID 和处理器亲和性,并打印到控制台。然后,我们等待信号量,执行一些工作(这里省略了具体的工作),最后恢复线程的处理器亲和性。

注意,以上示例仅为演示使用 CreateThread、CreateSemaphore、GetThreadAffinityMask 和 SetThreadAffinityMask 这些函数的基本用法。

希望对你有所帮助!

参考来源:

C++ CreateThread的使用
C++ —多线程之createthread创建线程
CreateThread函数

  • 49
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C线程中的CreateThread函数可以用来创建一个新的线程。它的原型是DWORD WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)。 在使用CreateThread函数时,需要注意一些细节。首先,在使用CRT库时,应该避免使用CreateThread函数来创建线程,而应该使用_beginthread函数来创建线程,并使用_endthread函数来销毁线程。因为使用CreateThread创建的线程没有为CRT库分配堆,可能会导致低内存错误而崩溃。 另外,在使用CreateThread函数创建线程时,需要传入参数lpStartAddress,它是一个指向线程函数的指针,用于指定线程的入口点。线程函数的原型应为DWORD WINAPI ThreadProc(LPVOID lpParameter),其中lpParameter参数可以用来传递线程函数需要的参数。 创建线程后,可以使用CloseHandle来关闭线程句柄。但是需要注意,关闭线程句柄并不会终止线程的执行,只是释放了句柄对象。要正确终止线程的执行,可以在线程函数中使用ExitThread函数或者让线程函数执行完毕自动终止。 总结来说,C线程中的CreateThread函数可以用来创建一个新的线程,但在使用时需要注意避免对CRT库的分配堆出现错误。同时,还需要传入线程函数的指针和参数来指定线程的入口点和参数。创建线程后,可以使用CloseHandle函数来关闭线程句柄,但要注意关闭句柄并不会终止线程的执行。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++CreateThread函数创建线程的用法和实例](https://blog.csdn.net/weixin_39795268/article/details/117157743)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值