zoukankan      html  css  js  c++  java
  • windows多线程编程实现 简单(1)

    内容:实现win32下的最基本多线程编程

    使用函数:

    #CreateThread#
    创建线程
    HANDLE WINAPI CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    SIZE_T dwStackSize,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    DWORD dwCreationFlags,
    LPDWORD lpThreadID
    );
    函数说明:param1 线程内核对象安全属性,一般传入NULL表示使用默认设置
    param2 表示线程栈空间大小。传入0,表示默认使用大小1MB
    param3 新线程的线程函数地址,多个线程可以使用同一个函数地址
    param4 传给线程函数的参数
    param5 指定额外的标志来控制线程的创建,为0表示线程创建之后立即可以进行调度,如果为CREATE_SUSPENDED则表示线程创建以后暂停运行,这样无法调度,直到调用ResumeThread()
    param6 返回线程的ID号,传入NULL表示不需要返回该线程ID号
    注意:尽量使用 _beginthreadex()代替使用CreateThread().标准C运行库与多线程矛盾。

      

    #WaitForMultipleObjects#
    同时等待多个对象的触发,也可以用来事件的分别触发,定时触发。
    DWORD WaitForMutilpleObjects(
    DWORD nCount,
    CONST HANDLE *lpHandles,
    BOOL fWaitALL,
    DWORD dwMilliseconds,
    );
    参数 nCount 句柄的最大数 最大值为MAXIMUM_WAIT_OBJECTS 64
    HANDLE 句柄数组指针,类型可以为EVENT,Mutex,Process,Thread,Semaphore数组
    bWaitAll 等待类型,如果为TRUE,则等待所有信号量再往下执行,FALSE当其中一个信号量有效时就向下执行    
    dwMilliseconds 超时事件 超时后就执行,如果为WSA_INFINTE永不超时,如果没有信号量就会死在这里。

     实现代码:线程IMM_PCentry和Def_DeferredTaskEntry交替运行。本程序并未实现同步,只是简单的多线程操作。

     1 #include <windows.h>
     2 #include <stdlib.h>
     3 #include <stdio.h>
     4 #include <process.h>
     5 
     6 #define SYN
     7 
     8 int index = 0;
     9 HANDLE hMainThread;
    10 HANDLE hIMMthread;
    11 HANDLE hMainThread_ID = 0;
    12 HANDLE hIMMthread_ID = 0;
    13 #ifdef SYN
    14 HANDLE Mutex_Main;
    15 HANDLE Mutex_Imm;
    16 #endif
    17 
    18 void WINAPI IMM_PCentry(LPVOID lpParameter)
    19 {
    20     //WaitForSingleObject(hMutex, INFINITE); //第二个参数为INFINITE表示一直等待,直到拥有互斥对象
    21     while (index < 200)
    22     {
    23 #ifdef SYN
    24         WaitForSingleObject(Mutex_Main, INFINITE);
    25 #endif
    26         index = index + 1;
    27         printf("IMM_PCentry hello %d id%d
    ", index, hIMMthread_ID);
    28 #ifdef SYN
    29         SetEvent(Mutex_Imm);
    30 #endif
    31     }
    32 
    33 }
    34 
    35 void WINAPI Def_DeferredTaskEntry(LPVOID lpParameter)
    36 {
    37     //WaitForSingleObject(hMutex, INFINITE); //第二个参数为INFINITE表示一直等待,直到拥有互斥对象
    38     while (index < 200)
    39     {
    40 #ifdef SYN
    41         WaitForSingleObject(Mutex_Imm, INFINITE);
    42 #endif
    43         index = index + 1;
    44         printf("Def_DeferredTaskEntry hello sharon6 %d id%d
    ", index, hMainThread_ID);
    45 #ifdef SYN
    46         SetEvent(Mutex_Main);
    47 #endif
    48     }
    49 
    50 }
    51 
    52 int main(void)
    53 {
    54 #ifdef SYN
    55     Mutex_Main = CreateEvent(NULL, 0, 0, NULL);
    56     Mutex_Imm = CreateEvent(NULL, 0, 0, NULL);
    57     SetEvent(Mutex_Imm);
    58 #endif 
    59 
    60     hMainThread = CreateThread(NULL, 0, IMM_PCentry, NULL, 0, &hMainThread_ID);
    61     hIMMthread = CreateThread(NULL, 0, Def_DeferredTaskEntry, NULL, 0, &hIMMthread_ID);
    62     WaitForSingleObject(hMainThread, INFINITE);
    63     WaitForSingleObject(hIMMthread, INFINITE);
    64     Sleep(200000);
    65     CloseHandle(hMainThread);
    66     CloseHandle(hIMMthread);
    67     return 0;
    68 }

    未定义#define SYN时打印结果如下

    index为两个线程的共享内存变量。
      Def_DeferredTaskEntry线程第一次结束后Count = Count + 1 = 1;
      IMM_Pcentry线程开始, 执行完 index = index + 1; 线程被Def_DeferredTaskEntry抢占IMM_Pcentry上下文保存了index = 2的值;
      Def_DeferredTaskEntry线程开始执行,执行到打印hello 7后,执行到index = index + 1,Def_DeferredTaskEntry线程又被IMM_Pcentry线程抢占,Def_DeferredTaskEntry线程保存线程上下文,包括index = 8;
      继续执行上次线程IMM_Pcentry执行的地方,恢复上下文环境,当时保存的是index = 2的值,此时被打印出来。线程IMM_Pcentry继续正常执行。

      可以发现,正是因为线程的不断切换,导致index不是每次都加一变化。

    为了达到index正常加1的目的,于是利用信号量来实现线程的控制。增加#define SYN宏定义

    #CreateEvent#
    HANDLE CreateEvent(
    LPSECURITY_ATTRIBUTES lpEventAttributes,//安全属性
    BOOL bManualReset,//复位方式
    BOOL bInitialState,//初始状态
    LPCSTR ipName//对象名称
    );
    #SetEvent#
    一种Win32系统编程事件API
    CEvent::SetEvent
    BOOL SetEvent(HANDLE hEvent);
    其中hEvent表示句柄,返回值;如果操作成功,则返回非零值,否则为0.

    可以看到打印结果,两个线程执行顺序得到了控制。注意这里并不是通过加锁来得到想要得结果。

  • 相关阅读:
    27、BLASTN的参数
    6、R语言绘制带errorbar 的柱状图
    26、HDF5 文件格式简介
    25、转录本(transcript)组成(gtf文件的第三列)
    6、perl创建模块(Exporter)及路径 引用 嵌套 查询模块
    24、嵌合体序列Chimeras
    24、sam- 详解
    22、IDP-ASE
    21 、GPD-PSL-VCF
    EasyUI 中easyui-textbox和easyui-searchbox文本框的点击事件。
  • 原文地址:https://www.cnblogs.com/jiawang/p/6243259.html
Copyright © 2011-2022 走看看