Windows线程
admin
2024-01-21 03:29:39
0

Windows线程

线程基础
  • Windows线程是可以执行的代码的实例。

    系统是以线程为单位调度程序,一个程序中可以有多个线程,实现多任务的处理。主线程只能有一个。

  • Windows线程的特点

    1. 线程都具有1个ID
    2. 每个线程都具有自己的内存栈,其余的共享。
    3. 同一进程中的线程使用同一个地址空间。(除了栈空间)
  • 线程的调度

    操作系统将CPU的执行时间划分为时间片,依次根据时间片执行不同的线程。

    线程轮询: 线程A -> 线程B ->线程A …

创建线程
  • 创建线程

    HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes , // 安全属性,已废弃, NULLSIZE_T dwStackSize, // 线程栈的大小  按1M对齐,最少1MLPTHREAD_START_ROUTINE lpStartAddress, // 线程处理函数的函数地址,自己定义由系统调用LPVOID lpParameter, // 传递给线程处理函数的参数DWORD dwCreationFlags, // 线程的创建方式(立即执行&挂起方式)// 0 -> 立即启动// CREATE_SUSPENDED -> 挂起LPDWORD lpThreadId // 创建成功,返回线程的ID
    ); // 创建成功,返回线程句柄  ( 线程句柄和线程ID都可以代表线程 )
    
  • 定义线程处理函数

    DWORD WINAPI ThreadProc(LPVOID lpParameter // 创建线程时,传递给线程的参数
    );
    

Demo

#include 
#include 
DWORD CALLBACK TestProc(LPVOID pParam){char * pszText = (char *) pParam;printf("%s",pszText);
}
int main(){DWORD nID = 0;char * pszText = "******";HANDLE hThread = CreateThread(NULL,0,TestProc,pszText,0,&nID);getchar();return 0;
}

子线程正常执行->要保证主线程不结束

销毁线程
  • 挂起

    DWORD SuspendThread(HANDLE hThread // 线程句柄
    );
    
  • 唤醒

    DWORD ResumeThread(HANDLE hThread  // 线程句柄
    );
    
  • 结束指定线程

    BOOL TerminateThread(HANDLE hThread, // 线程句柄DWORD dwExitCode // 退出码,一般没用
    );
    
  • 结束函数所在的线程

    VOID ExitThread(DWORD dwExitCode // 退出码,没有实际意义
    );
    // 自杀 -> 只能干掉调用的线程
    
线程相关操作
  • 获取当前线程ID

    GetCurrentThreadId();
    
  • 获取当前线程的句柄

    GetCurrentThread();
    
  • 等候单个句柄有信号

    VOID WaitForSingleObject(HANDLE handle , // 句柄BUFF的地址DWORD dwMilliseconds // 最长等候时间 ms// INFINITE 一直等待
    );
    // 有信号时会立即返回
    // 没有信号会阻塞
    

    线程句柄是可等候句柄: 有信号和无信号状态

  • 同时等候多个句柄有信号

    DWORD WaitForMultipleObject(DWORD nCount, // 句柄数量CONST HANDLE *lpHandles, // 句柄BUFF的地址BOOL bWaitAll, // 等候方式// TRUE : 所有句柄都有信号才会返回// FALSE: 只要有一个有信号就返回DWORD dwMilliseconds // 等候时间  INFINITE
    );
    

    可等候句柄

  • 线程信号

    • 当线程处于执行状态时,线程无信号
    • 当线程结束那刻,线程有信号
线程同步
原子锁
  • 当多个线程对同一个数据进行原子操作,会产生结果丢失,比如算术运算

  • 使用原子锁函数

    InterlockedIncrement   // ++ 操作符
    InterlockedDecrement   // --
    InterlockedCompareExchange   // 三目运算符 
    InterlockedExchange    // = 赋值
    

    原子锁的实现,直接对数据所在的内存操作,并且任何一个瞬间只能有一个线程访问。

  • 只能对运算符加锁,效率高,但是麻烦

互斥锁
  • 相关问题

    多线程下代码或者资源的共享使用

  • 互斥的使用

    1. 创建互斥

      HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, // 安全数据(NULL)BOOL bInitialOwner, // 初始的拥有者 TRUE/FALSE// TRUE: 哪个线程创建哪个线程拥有// FALSE: 都不拥有LPCTSTR lpName // 命名
      ); // 创建成功返回互斥句柄
      // 互斥句柄,也是可等候句柄
      
      • 在任何时间点上只有一个线程拥有互斥, 独占性和排他性

      • 当任何线程都不拥有互斥,互斥有信号,任何一个线程拥有互斥,互斥就没有信号

    2. 等候互斥

      WaitFor… 函数

      互斥的等候遵循谁先等候谁先获得

      也就是加锁

    3. 释放互斥

      BOOL ReleaseMutex(HANDLE hMutex // 互斥锁句柄
      );
      
    4. 关闭互斥句柄

      CloseHandle
      

demo

#include 
#include HANDLE hmutex; // 接收互斥句柄 DWORD CALLBACK TestProc(LPVOID pParam){char * pszText = (char *) pParam;int i ;while(1){WaitForSingleObject(hmutex,INFINITE);for(i = 0;iprintf("%c",pszText[i]);Sleep(125);}printf("\n");ReleaseMutex(hmutex); } 
}
int main(){hmutex = CreateMutex(NULL,FALSE,NULL); DWORD nID1 = 0;DWORD nID2 = 0;char * pszText1 = "******";char * pszText2 = "------";HANDLE hThread1 = CreateThread(NULL,0,TestProc,pszText1,0,&nID1);HANDLE hThread2 = CreateThread(NULL,0,TestProc,pszText2,0,&nID2);getchar();CloseHandle(hmutex);return 0;
}
事件
  • 相关问题

    线程之间的通知问题

  • 事件的使用

    1. 创建事件

      HANDLE CreateEvent(LPSEURITY_ATTRIBUTES lpEventAttributes, // 安全属性BOOL bManualReset, // 事件重置(复位)方式 有信号 -> 无信号// TRUE  手动// FALSE 自动 --> 读取信号一次就会自动复位// 触发 无信号 ->有信号BOOL bInitialState ,// 事件初始状态,TRUE 有信号LPCTSTR lpName // 事件命名,可以为空
      );// 创建成功返回事件句柄
      

      可等候句柄

      事件的有信号无信号可控制

    2. 等候事件

      WaitForSingleObject  / WaitForMultipleObjects
      // 自动复位方式,会自动复位
      
    3. 触发事件( 将事件设置为有信号状态)

      BOOL SetEvent(HANDLE hEvent //handle to event
      );
      
    4. 复位事件( 将事件设置为无信号状态 )

      BOOL ResetEvent(HANDLE hEvent
      );
      
    5. 关闭事件

      CloseHandle
      

要小心事件的死锁问题

demo

#include 
#include 
HANDLE g_hEvent = 0; // 接收事件句柄DWORD CALLBACK PrintProc(LPVOID pParam){while(1){WaitForSingleObject(g_hEvent,INFINITE); // 等待信号 ResetEvent(g_hEvent); printf("......\n");}
}DWORD CALLBACK CtrlProc(LPVOID pParam){while(1){Sleep(1000);SetEvent(g_hEvent);}
} 
int main(){g_hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);DWORD nID = 0;HANDLE hThread[2] = {0};hThread[0] = CreateThread(NULL,0,PrintProc,NULL,0,&nID); hThread[1] = CreateThread(NULL,0,CtrlProc,NULL,0,&nID);WaitForMultipleObjects(2,hThread,TRUE,INFINITE);CloseHandle(g_hEvent);return 0; 
}
信号量
  • 相关的问题

    作用类似于事件,解决通知的相关问题。

    提供一个计数器,可以设置次数

  • 信号量的使用

    1. 创建信号量

      HANDLE CreateSemaphore(LPSECTRITY_ATTRIBUTES lpSemaphoreAttributes, // 安全属性LONG lInitialCount, // 初始化信号量数量// 信号量计数值为0时,没有信号// 信号量计数值不为0,有信号LONG lMaximumCount, // 信号量最大个数LPCTSTR lpName // 命名
      );// 创建成功返回信号量句柄
      

      可等候句柄

    2. 等候信号量

      WaitFor ...
      // 每等候通过一次,信号量的信号减1,直到为0阻塞
      
    3. 给信号量指定计数值

      BOOL ReleaseSemaphore(HANDLE hSemaphore, // 信号量句柄LONG lReleaseCount ,// 释放数量LPLONG lpPreviousCount // 返回的信息,返回释放前原来信号量的数量,可以为NULL
      );
      
    4. 关闭句柄

      CloseHandle
      

demo

#include 
#include 
HANDLE g_hSema = 0;// 保存信号量句柄DWORD CALLBACK TestProc(LPVOID pParam){while(1){WaitForSingleObject(g_hSema,INFINITE);printf("*****\n");}
}int main(){g_hSema = CreateSemaphore(NULL,3,10,NULL);DWORD nID = 0;HANDLE hThread = CreateThread(NULL,0,TestProc,NULL,0,&nID);getchar();ReleaseSemaphore(g_hSema,5,NULL);WaitForSingleObject(hThread,INFINITE);CloseHandle(g_hSema);	return 0;
}

相关内容

热门资讯

原创 4... 写在文章前的声明:在本文之前的说明:本文中所列的投资信息,只是一个对基金资产净值进行排行的客观描述,...
胜宏科技港股大涨49% 做完英... 记者 陈月芹 4月21日,全球AI算力板龙头胜宏科技(02476.HK)登陆港交所,上市首日股价大涨...
永赢基金:聚焦“科技新锐”,科... 数据来源:Wind,时间统计区间为2025/1/1-2026/4/21,指数过往表现不预示未来,不构...
五大阅读趋势显现!当当网发布2... 在第31个世界读书日即将来临之际及首个全民阅读活动周期间,当当网正式发布2026国民阅读洞察报告。 ...
业绩逐季回暖 老百姓大药房一季... 上证报中国证券网讯(记者 夏子航)4月22日晚,老百姓大药房发布2025年年报和2026年一季报。今...
中国20强城市大洗牌:苏州接近... 中国的城市经济竞争格局一直在变化,每年发布的GDP数据都会对城市经济实力进行重新排列。2025年榜又...
直击金宏气体股东会:预期年内氦... 《科创板日报》4月22日讯(记者 郭辉)金宏气体日前举行2025年度股东大会。会上该公司审议了公司年...
5月1日起,俄据悉将叫停哈萨克... 据行业消息人士透露,俄罗斯将于5月1日起停止经友谊管道转运哈萨克斯坦输往德国的石油,相关调整计划已送...
深化具身智能生态布局 京东携手... 4 月 22 日,京东与国内消费级人形机器人头部企业松延动力正式达成三年期战略合作。双方将围绕产品研...
原创 帮... 先问你一个问题,美伊停火今晚到期,按常理避险情绪该升温,黄金应该涨吧?结果恰恰相反——原油涨了,黄金...
300295、600889,将... 三六五网、南京化纤,将被*ST。 公司股票自4月23日开市起停牌一天,于4月24日开市起复牌并实施退...
能源大变天!外媒:羡慕中国的石... 这一次油价突破 110 美元的能源危机,着实魔幻。如果放在十年前,没人会相信中国能在这场风波中获利,...
黄金涨跌两难,现在还能上车吗? 中新网4月22日电(记者 左雨晴) 四月以来,美伊局势反复拉扯,美联储降息预期一变再变。黄金价格在4...
“我身体健康”,库克现身员工大... 当地时间4月21日,受苹果官宣CEO换届影响,公司股价盘中下探超2%,总市值失守4万亿美元关口,收盘...
库克留下一个悬念 工程师能否拯救创新节奏? 听筒Tech(ID:tingtongtech)原创 文 | 赵 森 ...
探索消费信贷与社交支付深度融合... 腾讯这一金融产品再添新功能,4月19日,北京商报记者注意到,微信分付灰度测试转账功能引发热议,在向微...
土耳其主要银行股指早盘下跌2% 每经AI快讯,4月20日,土耳其主要银行股指早盘下跌2%。 每日经济新闻
好用的OTA代运营源头厂家 在如今竞争激烈的酒旅行业中,OTA代运营服务成为了众多酒店、民宿提升竞争力的关键。但市场上的代运营厂...
成都五一出游全国热门第三 “五一”假期临近,同程旅行最新发布的《2026“五一”旅行趋势报告》显示,今年“五一”期间成都同时位...