`

windows C++ 用信号量控制线程

阅读更多

很好的控制线程,让线程互斥,互相协调工作,共享数据,这个问题有很多种解决办法,不过我个人觉得使用信号量控制线程特别方便。会想到用多线程控制程序,是由于上学期我们要做一个控制电机转速的课程设计,开始编写的程序都是一个线程控制的。后来课程设计结束了,一次在看多线程的演示程序的时候突然想到,原来的那个电机控制程序完全可以写成多线程,可是由于课程设计结束了,没有硬件供你调试,就自己写了个多线程的练习程序。
控制信号量几个主要的函数:

WaitForSingleObject();//等待信号量有效
CreatSemaphore();//申请信号量
OpenSemaphore();//打开信号量
ReleaseSemaphore();//释放信号量

 
下面来看看控制多线程要用到的东西:

HANDLE ptrSpdUpDown;
HANDLE ptrUpDownDraw;
HANDLE ptrDrawSpd; //申请指向信号量的句柄
  ptrSpdUpDown = ::CreateSemaphore(NULL, 0, 1, NULL);
  ptrUpDownDraw = ::CreateSemaphore(NULL, 0, 1, NULL);
  ptrDrawSpd = ::CreateSemaphore(NULL, 1, 1, NULL);//实例化三个信号量

bOnOff=true;//线程状态控制量 开启三个线程
    m_tWriteSpeed=AfxBeginThread(WriteSpeed,
      &m_sWriteSpeed,
      THREAD_PRIORITY_NORMAL,
      0,
      CREATE_SUSPENDED);
    m_tWriteSpeed->ResumeThread();
    m_tWriteUpDown=AfxBeginThread(WriteUpDown,
      &m_sWriteUpDown,
      THREAD_PRIORITY_NORMAL,
      0,
      CREATE_SUSPENDED);
    m_tWriteUpDown->ResumeThread();
    m_tDrawWindow=AfxBeginThread(DrawWindow,
      &m_sDrawWindow,
      THREAD_PRIORITY_NORMAL,
      0,
      CREATE_SUSPENDED);
    m_tDrawWindow->ResumeThread();

//三个线程函数
UINT WriteSpeed(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    WaitForSingleObject(ptrDrawSpd,INFINITE);
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iSpeed=iUp+iDown+rand();
    ReleaseSemaphore(ptrSpdUpDown,1,NULL);
    sTr.Format("%d",iNo);
    sMe.Format("%d",iSpeed);
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe);
    iNo++;
  }
  return 0;
}
UINT WriteUpDown(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    WaitForSingleObject(ptrSpdUpDown,INFINITE);
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iUp=iSpeed-rand();
    iDown=iSpeed+rand();
    ReleaseSemaphore(ptrUpDownDraw,1,NULL);
    sTr.Format("%d",iNo);
    sMe.Format("%d",iUp);
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe);
    iNo++;
  }
  return 0;
}
UINT DrawWindow(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    WaitForSingleObject(ptrUpDownDraw,INFINITE);
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr+"已经接到信号");
    ::Sleep(1000);
    sTr.Format("%d",iNo);
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr);
    iNo++;
    ReleaseSemaphore(ptrDrawSpd,1,NULL);
  }
  return 0;
}

 

上面的方法是先申请信号量的句柄然后再实例化信号量 下面这种方法是直接申请信号量 两种方法基本相同

CSemaphore ptrSpdUpDown(0, 1);
CSemaphore ptrUpDownDraw(0, 1);
CSemaphore ptrDrawSpd(1, 1);//#include <atlsync.h>注意在stdafx.h手动包含这个文件

 在各个线程函数中不用WaitForSingleObject了要使用Lock()UnLock();
下面是使用CSemaphore后在各个线程函数中使用Lock()UnLock()替换掉WaitForSingleObject的结果

UINT WriteSpeed(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    ptrDrawSpd.Lock(); 
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iSpeed=iUp+iDown+rand();
    ReleaseSemaphore(ptrSpdUpDown,1,NULL);
    ptrSpdUpDown.Unlock();
    sTr.Format("%d",iNo);
    sMe.Format("%d",iSpeed);
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe);
    iNo++;
  }
  return 0;
}
UINT WriteUpDown(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    ptrSpdUpDown.Lock();
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iUp=iSpeed-rand();
    iDown=iSpeed+rand();
    ReleaseSemaphore(ptrUpDownDraw,1,NULL);
    ptrUpDownDraw.Unlock();
    sTr.Format("%d",iNo);
    sMe.Format("%d",iUp);
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe);
    iNo++;
  }
  return 0;
}
UINT DrawWindow(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    ptrUpDownDraw.Lock();
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr+"已经接到信号");
    ::Sleep(1000);
    sTr.Format("%d",iNo);
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr);
    iNo++;
    ReleaseSemaphore(ptrDrawSpd,1,NULL);
    ptrDrawSpd.Unlock();
}
  return 0;
}

 推荐使用第一种方法,第一种方法只声明了句柄,当信号量实例化的时候句柄才指向三个信号量。所以更加支持多态。

程序初始化
Click to Open in New Window

程序运行中
Click to Open in New Window

分享到:
评论

相关推荐

    c++多线程同步——信号量

    MFC(Microsoft Foundation Classes)虽然主要用于Windows开发,但它并不直接支持C++11多线程特性,因此可能需要额外的手段来实现信号量。 在MFC工程中,我们可以通过创建一个自定义的信号量类,基于Windows API的`...

    windowsC++多线程加锁信号量共享内存

    在"threadlock4"这个文件中,很可能包含了示例代码或者详细教程,演示了如何在Windows环境下使用C++的多线程、互斥锁、信号量和共享内存。通过阅读和理解这个文件,开发者可以学习到如何在实际项目中有效地管理和...

    Visual C++信号量线程同步的简单实例工程

    本实例工程“Visual C++信号量线程同步的简单实例工程”聚焦于如何通过信号量(Semaphore)实现线程间的协调与同步,以确保资源的有效管理和避免竞态条件。 首先,我们需要理解什么是信号量。信号量是一种同步原语...

    线程同步机制代码,用c++写的,:使用Windows互斥信号量操作函数和同步机制的Peterson,实现进程互斥和同步

    小实验二:使用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置 小实验三:根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和...

    跨平台的C++线程模板类和信号量及互斥量模板类

    在C++编程中,跨平台性是一个重要的考量因素,特别是在涉及到操作系统底层机制如线程、锁和信号量等时。本文将深入探讨标题和描述中提及的“跨平台的C++线程模板类”以及“信号量及互斥量模板类”。 首先,线程是...

    c++多线程编程的十个例子

    为了防止这种问题,我们可以使用同步机制,如互斥量(`std::mutex`)、条件变量(`std::condition_variable`)和信号量(`std::semaphore`)。一个例子可能是两个线程共享一个资源,一个线程读取,另一个线程写入,互斥量...

    使用信号量实现线程同步

    在Windows系统中,信号量作为内核对象被广泛使用,可以用来控制对共享资源的访问。 信号量的核心概念是“计数”,它可以是正整数或零。当计数为非零时,表示资源可用;计数为零,则表示资源暂时不可用。线程通过...

    qt5多线程,信号量,互斥量,等待条件

    信号量(Semaphore)是一种用于控制对共享资源访问的同步机制。在QT5中,我们可以使用QSemaphore类来实现。信号量维护了一个计数值,当线程尝试获取资源时,计数值会减一;当线程释放资源时,计数值会加一。如果计...

    信号量机制实现线程同步

    信号量机制是操作系统中一种重要的同步机制,它用于控制对共享资源的访问,以避免多线程并发执行时出现的数据不一致性或竞态条件。在本文中,我们将深入探讨信号量的概念、类型以及如何在实际编程中应用信号量来实现...

    C++多线程控制例子

    线程间的通信可以通过共享内存、信号量、事件对象等方式实现。例如,可以使用`std::atomic`类型进行原子操作,或者在保护下访问共享数据(如在互斥量保护下)。 **6. ThrdCtrlPanel** 在本示例中,`ThrdCtrlPanel`...

    VC线程信号量的使用举例

    在VC++环境中,我们通常使用Windows API来管理线程的同步和通信,其中信号量(Semaphore)就是一种常用工具。本文将通过一个简单的VC线程信号量使用例子来介绍其工作原理和应用。 信号量是一种同步机制,用于控制对...

    c++实现多线程同步

    本文将深入探讨如何在C++中实现多线程以及如何利用信号量进行线程同步。 首先,我们需要理解什么是多线程。在单线程程序中,执行流是线性的,而多线程允许程序同时执行多个不同的任务。这通常会提高程序的响应性和...

    Windows多线程编程技术与实例(C++)(PDF)

    《Windows多线程编程技术与实例(C++)》是一本深入探讨Windows环境下多线程编程的书籍,特别适合正在学习或已经从事C++多线程开发的人员阅读。本书通过丰富的实例,详细讲解了如何在Windows操作系统中利用C++进行...

    VC多线程编程,利用信号量进行控制

    线程间的有效通信是多线程程序设计的关键,而信号量(Semaphore)作为一种同步机制,被广泛用于控制对共享资源的访问。 信号量是一种计数器,可以用来控制对有限资源的并发访问。在多线程环境中,当资源数量有限,...

    信号量实现多线程同步

    利用多线程原理模拟生产与消费的互斥同步过程,使用了信号量

    C++ 多线程日志记录

    在日志记录中,我们可以用信号量来限制同时写入日志的线程数量,防止过多线程同时操作日志文件导致的竞争条件。 临界区(Critical Section)是指一段需要互斥访问的代码区域。在C++中,可以使用`std::mutex`来保护...

    c++ builder 多线程

    2. **信号量(Semaphore)**: 信号量可以控制同时访问资源的线程数量。`CreateSemaphore`函数创建,`WaitForMultipleObjects`等待。 3. **事件(Event)**: 事件可以用于线程间的同步和通信。`CreateEvent`创建,`...

    C++11实现多线程电梯运行

    可以使用信号量(`std::semaphore`)或共享数据结构(如`std::atomic`)来实现。 4. **调度策略**:电梯可能需要根据优先级或预设的策略来决定下一个服务的楼层,这需要设计合理的算法。 5. **资源管理**:考虑到...

    Windows 多线程API C++类的封装

    6. **syncronization objects**:例如事件、信号量、互斥量等,作为成员变量,提供线程同步的接口。 在类的设计中,可以考虑使用模板,使得线程函数能够处理不同类型的参数。还可以添加异常安全性和资源管理,例如...

Global site tag (gtag.js) - Google Analytics