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;
}

相关内容

热门资讯

【IPO追踪】零成交常态化,解... 港股市场最尴尬的处境,莫过于股价跌跌不休,连交易都无人问津。6月24日,美联股份(02671.HK)...
SK海力士冲刺美国上市,ADR... 若顺利完成,相关交易最快有望于下个月启动,并成为韩国企业历史上规模最大的海外股权融资项目之一。 人工...
伯恩斯坦:锂价上行周期远未结束... 6月23日消息,伯恩斯坦最新研报中上调锂价预测,并将 天齐锂业(002466.SZ)A股目标价从73...
原创 全... 中国与印度尼西亚之间,正在上演一场围绕镍矿资源的激烈博弈。令人颇感意外的是,这场博弈的主动挑起者竟然...
企业出海ESG合规与可持续发展... 中新网北京6月24日电 (记者 尹倩芸)2026年北京市“走出去”系列活动——企业出海ESG合规与可...
原创 中... 聊到现在的楼市,身边人想法差得挺远。有人还在等跌,觉得再观望一阵更稳妥。也有人盯上了官方最近放的几个...
企业微信Agent内测悄启 主... 继微信AI助手开启内测后,企业微信紧跟步伐开启了AI助手的内测,但跟微信嵌入的不是同一个Agent。...
马斯克官宣Starmind太空... IT之家 6 月 24 日消息,埃隆 · 马斯克(Elon Musk)今天(6 月 24 日)在 X...
5000亿市值巨头,盘中涨停 6月24日午后,立讯精密股价直线拉升,盘中触及涨停后开板。截至发稿,该股报75.39元/股,涨8.6...
中兴通讯爱理财?额度2年翻倍至... 图片来源:图虫创意 钱的流向,往往折射出一家企业的战略重心。 6月17日,中兴通讯在深圳召开股东大会...
中国掌控全球过半铜冶炼产能,美... 【文/观察者网 王恺雯】 面对中国在铜冶炼和精炼上的主导地位,美国试图通过关税及工业政策复兴国内铜产...
年内92宗IPO获受理 创业板... 来源:滚动播报 (来源:北京商报) 随着创业板深化改革持续推进,今年创业板IPO申报热度攀升,替代北...
SpaceX跌破IPO首日开盘... 来源:滚动播报 来源:中国基金报 【导读】SpaceX股价连续重挫 中国基金报记者 张舟 Space...
酒庄头条:在郎酒庄园,看见世界... 文/酒庄头条 中国酒业该向何处去?又如何走向国际市场?酿酒业是有根产业历史经典产业,郎酒以全球视野开...
100个选基指标|利润总额,真... 推荐阅读: 100个选基指标丨自然年度收益率,最简单,也最重要(第一期) 100个选基指标丨区间收益...
连云港开发区为AI“制药”按下... 从人才赋能、校地协同到产业落地,今年以来,连云港开发区通过一系列密集举措构建起全链条、立体化的产业赋...
1.08亿控股德维嘉:无锡振华... 一家传统汽车冲压件上市公司,正试图用一笔亿元级别的现金收购,为自己贴上“汽车智能化”的标签。 6月2...
ATFX:SpaceX下跌16... 来源:市场资讯 6月23日,ATFX汇评:美国航空航天代表性个股SpaceX,上市六个交易日,三个交...
嘉实基金李涛:长期视角决策未来... 嘉实成长共赢混合基金经理李涛表示, 投资理财本质上是一场长期主义的远行,权益投资本质是追求赚取产业与...
震裕科技可转债发行申请获深交所... 雷达财经 文|苏静 编|深海 6月23日, 震裕科技(300953)发布关于公司向不特定对象发行可转...