很好的控制线程,让线程互斥,互相协调工作,共享数据,这个问题有很多种解决办法,不过我个人觉得使用信号量控制线程特别方便。会想到用多线程控制程序,是由于上学期我们要做一个控制电机转速的课程设计,开始编写的程序都是一个线程控制的。后来课程设计结束了,一次在看多线程的演示程序的时候突然想到,原来的那个电机控制程序完全可以写成多线程,可是由于课程设计结束了,没有硬件供你调试,就自己写了个多线程的练习程序。
控制信号量几个主要的函数:
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;
}
推荐使用第一种方法,第一种方法只声明了句柄,当信号量实例化的时候句柄才指向三个信号量。所以更加支持多态。
程序初始化

程序运行中

分享到:
相关推荐
MFC(Microsoft Foundation Classes)虽然主要用于Windows开发,但它并不直接支持C++11多线程特性,因此可能需要额外的手段来实现信号量。 在MFC工程中,我们可以通过创建一个自定义的信号量类,基于Windows API的`...
在"threadlock4"这个文件中,很可能包含了示例代码或者详细教程,演示了如何在Windows环境下使用C++的多线程、互斥锁、信号量和共享内存。通过阅读和理解这个文件,开发者可以学习到如何在实际项目中有效地管理和...
本实例工程“Visual C++信号量线程同步的简单实例工程”聚焦于如何通过信号量(Semaphore)实现线程间的协调与同步,以确保资源的有效管理和避免竞态条件。 首先,我们需要理解什么是信号量。信号量是一种同步原语...
小实验二:使用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置 小实验三:根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和...
在C++编程中,跨平台性是一个重要的考量因素,特别是在涉及到操作系统底层机制如线程、锁和信号量等时。本文将深入探讨标题和描述中提及的“跨平台的C++线程模板类”以及“信号量及互斥量模板类”。 首先,线程是...
为了防止这种问题,我们可以使用同步机制,如互斥量(`std::mutex`)、条件变量(`std::condition_variable`)和信号量(`std::semaphore`)。一个例子可能是两个线程共享一个资源,一个线程读取,另一个线程写入,互斥量...
在Windows系统中,信号量作为内核对象被广泛使用,可以用来控制对共享资源的访问。 信号量的核心概念是“计数”,它可以是正整数或零。当计数为非零时,表示资源可用;计数为零,则表示资源暂时不可用。线程通过...
信号量(Semaphore)是一种用于控制对共享资源访问的同步机制。在QT5中,我们可以使用QSemaphore类来实现。信号量维护了一个计数值,当线程尝试获取资源时,计数值会减一;当线程释放资源时,计数值会加一。如果计...
信号量机制是操作系统中一种重要的同步机制,它用于控制对共享资源的访问,以避免多线程并发执行时出现的数据不一致性或竞态条件。在本文中,我们将深入探讨信号量的概念、类型以及如何在实际编程中应用信号量来实现...
线程间的通信可以通过共享内存、信号量、事件对象等方式实现。例如,可以使用`std::atomic`类型进行原子操作,或者在保护下访问共享数据(如在互斥量保护下)。 **6. ThrdCtrlPanel** 在本示例中,`ThrdCtrlPanel`...
在VC++环境中,我们通常使用Windows API来管理线程的同步和通信,其中信号量(Semaphore)就是一种常用工具。本文将通过一个简单的VC线程信号量使用例子来介绍其工作原理和应用。 信号量是一种同步机制,用于控制对...
本文将深入探讨如何在C++中实现多线程以及如何利用信号量进行线程同步。 首先,我们需要理解什么是多线程。在单线程程序中,执行流是线性的,而多线程允许程序同时执行多个不同的任务。这通常会提高程序的响应性和...
《Windows多线程编程技术与实例(C++)》是一本深入探讨Windows环境下多线程编程的书籍,特别适合正在学习或已经从事C++多线程开发的人员阅读。本书通过丰富的实例,详细讲解了如何在Windows操作系统中利用C++进行...
线程间的有效通信是多线程程序设计的关键,而信号量(Semaphore)作为一种同步机制,被广泛用于控制对共享资源的访问。 信号量是一种计数器,可以用来控制对有限资源的并发访问。在多线程环境中,当资源数量有限,...
利用多线程原理模拟生产与消费的互斥同步过程,使用了信号量
在日志记录中,我们可以用信号量来限制同时写入日志的线程数量,防止过多线程同时操作日志文件导致的竞争条件。 临界区(Critical Section)是指一段需要互斥访问的代码区域。在C++中,可以使用`std::mutex`来保护...
2. **信号量(Semaphore)**: 信号量可以控制同时访问资源的线程数量。`CreateSemaphore`函数创建,`WaitForMultipleObjects`等待。 3. **事件(Event)**: 事件可以用于线程间的同步和通信。`CreateEvent`创建,`...
可以使用信号量(`std::semaphore`)或共享数据结构(如`std::atomic`)来实现。 4. **调度策略**:电梯可能需要根据优先级或预设的策略来决定下一个服务的楼层,这需要设计合理的算法。 5. **资源管理**:考虑到...
6. **syncronization objects**:例如事件、信号量、互斥量等,作为成员变量,提供线程同步的接口。 在类的设计中,可以考虑使用模板,使得线程函数能够处理不同类型的参数。还可以添加异常安全性和资源管理,例如...