C++多线程编程笔记

Windows系统为我们提供了相关API,我们可以使用它们来进行多线程编程。

创建线程的函数:

HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
    SIZE_T dwStackSize,                       // initial stack size
    LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
    LPVOID lpParameter,                       // thread argument
    DWORD dwCreationFlags,                    // creation option
    LPDWORD lpThreadId                        // thread identifier
);

最简单的C++多线程程序:

#include <iostream>
#include <windows.h>
using namespace std;

DWORD WINAPI Fun(LPVOID lpParameter)
{
    while (1)
    {
        cout<<"Fun Display!"<<endl;
        Sleep(1000);
    }
}

int main()
{
    HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
    CloseHandle(hThread);
    while (1)
    {
        cout<<"Main Display!"<<endl;
        Sleep(1000);
    }
    return 0;
}

运行上面的程序会发现有些时候输出了换行,有些时候则没有输出换行,也有的时候输出了两个换行。这是因为多线程的程序是并发地运行的,多个线程之间如果共用了一些资源的话,并不能保证这些资源都能被正确地利用,因为资源并不是独占的。

改进后的程序如下:

#include <iostream>
#include <windows.h>
using namespace std;

HANDLE hMutex;

DWORD WINAPI Fun(LPVOID lpParameter)
{
    while (1)
    {
        WaitForSingleObject(hMutex, INFINITE);
        cout<<"Fun Display!"<<endl;
        Sleep(1000);
        ReleaseMutex(hMutex);
    }
}

int main()
{
    HANDLE hThread = CreateThread(NULL, 0, Fun, NULL, 0, NULL);
    hMutex = CreateMutex(NULL, false, "screen");
    CloseHandle(hThread);
    while (1)
    {
        WaitForSingleObject(hMutex, INFINITE);
        cout<<"Main Display!"<<endl;
        Sleep(1000);
        ReleaseMutex(hMutex);
    }
    return 0;
}

Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作。

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

该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:

  • lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为 NULL;
  • dwStackSize:指定了线程的堆栈深度,一般都设置为0;
  • lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc 是线程函数名;
  • lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;
  • dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
  • lpThreadId:该参数返回所创建线程的ID; 如果创建成功则返回线程的句柄,否则返回NULL。
DWORD SuspendThread(HANDLE hThread); 

该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止。

DWORD ResumeThread(HANDLE hThread); 

该函数用于结束线程的挂起状态,执行线程。

VOID ExitThread(DWORD dwExitCode); 

该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。

BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode); 

一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。各参数含义如下:

  • hThread:将被终结的线程的句柄;
  • dwExitCode:用于指定线程的退出码。

使用TerminateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源。因此,一般不建议使用该函数。

BOOL PostThreadMessage(
    DWORD idThread,
    UINT Msg,
    WPARAM wParam,
    LPARAM lParam
); 

该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回。

  • idThread:将接收消息的线程的ID;
  • Msg:指定用来发送的消息;
  • wParam:同消息有关的字参数;
  • lParam:同消息有关的长参数;

调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-26 00:29:46

C++多线程编程笔记的相关文章

多线程编程笔记

多线程的问题 在多线程应用中,子线程一定会修改某些公共资源(包括全局变量.磁盘文件等),这样很有可能会影响其它子线程.由于不同线程是并行执行的,有可能某个时刻某个线程对公共资源进行了部分修改,此时公共资源是无效的,CPU 切换到另一个线程执行并访问此公共资源,这样将有可能造成巨大灾难. 要解决此问题,就应该使需要相同公共资源的不同线程不能同时执行,所以多线程问题分析的基础是互斥. 线程同步和线程互斥 线程间的关系可以分为无关和相交两种.当多个线程无关的时候,其中某个线程的启动不会依赖于另一个线程

【C】多线程编程笔记

1. pthread_create(pthread类型指针变量 ,NULL ,函数 ,函数参数[多个参数用结构体传]) 2. pthread_join(pthread类型指针变量, 返回一般为null) pthread_join的作用: pthread_join()函数,以阻塞的方式等待thread指定的线程结束. 如果不用这个函数,直接create后,进程也会运行,但是主线程不会等待这些子线程是否已经运行结束,而继续向下运行,很快主线程就结束了,而子线程还未运行完,被迫结束. 加入pthrea

java笔记--使用线程池优化多线程编程

使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库连接池,线程池等. 在java1.5之后,java自带了线程池,在util包下新增了concurrent包,这个包主要作用就是介绍java线程和线程池如何使用的. 在包java.util.concurrent下的 Executors类中定义了Executor.ExecutorService.Sche

《Linux多线程编程手册》读书笔记

第二章 基本线程编程 1.(P25)如果多个线程等待同一个线程终止,则所有等待线程将一直等到目标线程终止.然后,一个等待线程成功返回,其余的等待线程将失败并返回ESRCH错误. 2.(P26)将新线程的pbe参数作为栈参数进行传递.这个线程参数之所以能够作为栈参数传递,是因为主线程会等待辅助线程终止.不过,首选方法是使用malloc从堆分配存储,而不是传递指向线程栈存储的地址.如果将该参数作为地址传递到线程栈存储,则该地址可能无效或者在线程终止时会被重新分配. 3.(P28)pthread_de

Java多线程编程(学习笔记)

一.说明 周末抽空重新学习了下多线程,为了方便以后查阅,写下学习笔记. 有效利用多线程的关键是理解程序是并发执行而不是串行执行的.例如:程序中有两个子系统需要并发执行,这时候需要利用多线程编程. 通过多线程的使用,可以编写出非常高效的程序.但如果创建了太多的线程,程序执行的效率反而会降低. 同时上下文的切换开销也很重要,如果创建太多的线程,CPU花费在上下文的切换时间将对于执行程序的时间. 二.Java多线程编程 概念 在学习多线程时,我们应该首先明白另外一个概念. 进程:是计算机中的程序关于某

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

GCD 多线程API编程笔记

GCD 是 iOS 编程中实现多线程的常用 API,使用方便,无须进行线程的管理,由系统代劳.同时GCD基于C实现,性能强. 在名著<Pro multithreading and memory management for iOS and OS X>(中文名:<Objective-C 高级编程 iOS与 OSX多线程和内存管理>)中,专门有章节讲解,特根据此书讲解做些笔记. 一 概要 GCD是Grand Central Dispatch(GCD)的缩写,是异步执行任务的技术之一.一

Java基础复习笔记系列 八 多线程编程

Java基础复习笔记系列之 多线程编程 1. 2.

VC多线程编程学习笔记(一)

最近两天在学多线程编程,有了一些心得,写下来和大家一起共勉.文中一些部分引用了韩耀旭的文章<多线程编程>http://www.vckbase.com/document/viewdoc/?id=1704和MSDN资料. 一.缘起 工作上要用到串口编程,本来一直是用mscomm控件来进行串口通讯的,后来觉得这个控件功能不灵活,想直接使用api编程,那就不可避免的要使用多线程技术:用一个支线程一直挂在那里监听串口,就不影响主线程的消息循环了. 二.为何要用多线程 有时候需要把程序的运行挂起一段时间,