抢红包练习

第一步:在第一个文本框中输入一个值,比如1000;
第二步:点击抢红包,同时创建3个线程,每个线程循环进行抢红包的操作,每次抢50;
第三步:使用Mutex进行线程控制,当第一个文本框中的值<50时,强红包线程结束.
特别说明:
1、四个文本框中的值总和应该为1000
2、强红包线程每次延时50毫秒.
3、使用WaitForMultipleObjects监听所有线程,当线程全部结束后,调用CloseHandle关闭句柄.

下面是代码实现,我是用MFC实现的。

// MutexExDlg.h : 头文件
// #pragma once // CMutexExDlg 对话框
class CMutexExDlg : public CDialogEx
{
// 构造
public:
CMutexExDlg(CWnd* pParent = NULL); // 标准构造函数 // 对话框数据
enum { IDD = IDD_MUTEXEX_DIALOG }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
static HANDLE hThread[];
static HANDLE m_Mutex;
static DWORD WINAPI ThreadProc0(LPVOID lpParameter);
static DWORD WINAPI ThreadProc1(LPVOID lpParameter);
static DWORD WINAPI ThreadProc2(LPVOID lpParameter);
static DWORD WINAPI ThreadProc3(LPVOID lpParameter); // 实现
protected:
HICON m_hIcon; // 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnBnClickedButton1();
static int m_Edit0;
static int m_Edit1;
static int m_Edit2;
static int m_Edit3;
};
// MutexExDlg.cpp : 实现文件
// #include "stdafx.h"
#include "MutexEx.h"
#include "MutexExDlg.h"
#include "afxdialogex.h" #ifdef _DEBUG
#define new DEBUG_NEW
#endif // CMutexExDlg 对话框 CMutexExDlg::CMutexExDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMutexExDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void CMutexExDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_Edit0);
DDV_MinMaxInt(pDX, m_Edit0, , );
DDX_Text(pDX, IDC_EDIT2, m_Edit1);
DDV_MinMaxInt(pDX, m_Edit1, , );
DDX_Text(pDX, IDC_EDIT3, m_Edit2);
DDV_MinMaxInt(pDX, m_Edit2, , );
DDX_Text(pDX, IDC_EDIT4, m_Edit3);
DDV_MinMaxInt(pDX, m_Edit3, , );
} BEGIN_MESSAGE_MAP(CMutexExDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMutexExDlg::OnBnClickedButton1)
END_MESSAGE_MAP() // CMutexExDlg 消息处理程序 BOOL CMutexExDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void CMutexExDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), ); // 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + ) / ;
int y = (rect.Height() - cyIcon + ) / ; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMutexExDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
} // 重写虚函数 PreTranslateMessage 屏蔽掉Esc键和Enter键
BOOL CMutexExDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
int keyCode = (int)pMsg->wParam;
if (keyCode == VK_ESCAPE || keyCode == VK_RETURN)
{
return TRUE;
}
}
return CDialogEx::PreTranslateMessage(pMsg);
} HANDLE CMutexExDlg::m_Mutex = NULL;
int CMutexExDlg::m_Edit0 = ;
int CMutexExDlg::m_Edit1 = ;
int CMutexExDlg::m_Edit2 = ;
int CMutexExDlg::m_Edit3 = ;
HANDLE CMutexExDlg::hThread[] = { NULL }; // 抢红包按钮点击事件处理函数
void CMutexExDlg::OnBnClickedButton1()
{
// 获取编辑框内容到str变量
CString str;
GetDlgItem(IDC_EDIT1)->GetWindowText(str);
// CString 转 int
m_Edit0 = _ttoi(str);
m_Edit1 = ;
m_Edit2 = ;
m_Edit3 = ;
// 这里需要创建一个线程 因为 WaitForMultipleObjects 会阻塞住 另外把this指针作为参数传递给线程,用于子线程更新编辑框内容
HANDLE hThread0 = ::CreateThread(NULL, NULL, ThreadProc0, this, NULL, NULL);
CloseHandle(hThread0);
} DWORD WINAPI CMutexExDlg::ThreadProc0(LPVOID lpParameter)
{
// bInitialOwner BOOL,如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有
// 创建一个互斥体
m_Mutex = ::CreateMutex(NULL, FALSE, L"test");
// 创建三个线程抢红包
hThread[] = ::CreateThread(NULL, NULL, ThreadProc1, lpParameter, NULL, NULL);
hThread[] = ::CreateThread(NULL, NULL, ThreadProc2, lpParameter, NULL, NULL);
hThread[] = ::CreateThread(NULL, NULL, ThreadProc3, lpParameter, NULL, NULL);
// 使用WaitForMultipleObjects监听所有线程,当线程全部结束后,调用CloseHandle关闭句柄.
WaitForMultipleObjects(, hThread, TRUE, -);
::CloseHandle(hThread[]);
::CloseHandle(hThread[]);
::CloseHandle(hThread[]);
::CloseHandle(m_Mutex);
return ;
} // 线程回调函数1
DWORD WINAPI CMutexExDlg::ThreadProc1(LPVOID lpParameter)
{
CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter;
while (true)
{
WaitForSingleObject(m_Mutex, -);
if (m_Edit0 < )
{
break;
}
m_Edit0 = m_Edit0 - ;
m_Edit1 = m_Edit1 + ;
// int 转 CString
CString str0;
str0.Format(_T("%d"), m_Edit0);
// 设置编辑框内容
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), str0);
CString str1;
str1.Format(_T("%d"), m_Edit1);
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT2), str1);
Sleep();
// 释放线程拥有的互斥体的控制权
ReleaseMutex(m_Mutex);
}
return ;
} // 线程回调函数2
DWORD WINAPI CMutexExDlg::ThreadProc2(LPVOID lpParameter)
{
CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter;
while (true)
{
WaitForSingleObject(m_Mutex, -);
if (m_Edit0 < )
{
break;
}
m_Edit0 = m_Edit0 - ;
m_Edit2 = m_Edit2 + ;
CString str0;
str0.Format(_T("%d"), m_Edit0);
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), str0);
CString str1;
str1.Format(_T("%d"), m_Edit2);
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT3), str1);
Sleep();
// 释放线程拥有的互斥体的控制权
ReleaseMutex(m_Mutex);
}
return ;
} // 线程回调函数3
DWORD WINAPI CMutexExDlg::ThreadProc3(LPVOID lpParameter)
{
CMutexExDlg* pDlg = (CMutexExDlg*)lpParameter;
while (true)
{
WaitForSingleObject(m_Mutex, -);
if (m_Edit0 < )
{
break;
}
m_Edit0 = m_Edit0 - ;
m_Edit3 = m_Edit3 + ;
CString str0;
str0.Format(_T("%d"), m_Edit0);
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT1), str0);
CString str1;
str1.Format(_T("%d"), m_Edit3);
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_EDIT4), str1);
Sleep();
// 释放线程拥有的互斥体的控制权
ReleaseMutex(m_Mutex);
}
return ;
}

C++线程同步与互斥之互斥体的更多相关文章

  1. Delphi线程同步(临界区、互斥、信号量)

    当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源. 例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件的字符数.当然,在整个文件调入内存之前,统计它的计数是 ...

  2. Delphi线程同步(临界区、互斥、信号量,包括详细代码)

    当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源. 例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件的字符数.当然,在整个文件调入内存之前,统计它的计数是 ...

  3. C#线程同步(3)- 互斥量 Mutex

    文章原始出处 http://xxinside.blogbus.com/logs/47162540.html 预备知识:C#线程同步(1)- 临界区&Lock,C#线程同步(2)- 临界区&am ...

  4. MFC线程(三):线程同步事件(event)与互斥(mutex)

    前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFu ...

  5. 线程同步(windows平台):互斥对象

    一:介绍 互斥对象是系统内核维护的一种数据结构,保证了对象对单个线程的访问权. 二:函数说明 创建互斥对象:    HANDLE CreateMutex(            LPSECURITY_ ...

  6. 线程同步方式之互斥量Mutex

    互斥量和临界区非常相似,只有拥有了互斥对象的线程才可以访问共享资源,而互斥对象只有一个,因此可以保证同一时刻有且仅有一个线程可以访问共享资源,达到线程同步的目的. 互斥量相对于临界区更为高级,可以对互 ...

  7. 【C#进阶系列】28 基元线程同步构造

    多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗 ...

  8. Delphi 线程同步技术(转)

    上次跟大家分享了线程的标准代码,其实在线程的使用中最重要的是线程的同步问题,如果你在使用线程后,发现你的界面经常被卡死,或者无法显示出来,显示混乱,你的使用的变量值老是不按预想的变化,结果往往出乎意料 ...

  9. C/C++ 实现多线程与线程同步

    多线程中的线程同步可以使用,CreateThread,CreateMutex 互斥锁实现线程同步,通过临界区实现线程同步,Semaphore 基于信号实现线程同步,CreateEvent 事件对象的同 ...

  10. C++线程同步的四种方式(Windows)

    为什么要进行线程同步? 在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作.更多的情况是一些线程进行某些处理操作,而其他的线程必须对其处理结果进行了解.正常情况下对这种处理结果的 ...

随机推荐

  1. 第09组 Beta冲刺(3/4)

    队名:软工9组 组长博客:https://www.cnblogs.com/cmlei/ 作业博客:https://edu.cnblogs.com/campus/fzu/SoftwareEngineer ...

  2. mysql性能测试-------重要!!!

    我们在做性能测试的目的是什么,就是要测出一个系统的瓶颈在哪里,到底是哪里影响了我们系统的性能,找到问题,然后解决它.当然一个系统由很多东西一起组合到一起,应用程序.数据库.服务器.中中间件等等很多东西 ...

  3. win7下查看进程端口

    一. 查看所有进程占用的端口 在开始-运行-cmd,输入:netstat –ano 可以查看所有进程 二.查看占用指定端口的程序 当你在用tomcat发布程序时,经常会遇到端口被占用的情况,我们想知道 ...

  4. apt与apt-get命令的区别

    apt 和 apt-get的区别 Debian 作为 Ubuntu.Linux Mint 和 elementary OS 等 Linux 操作系统的母板,其具有强健的「包管理」系统,它的每个组件和应用 ...

  5. 使用bert进行情感分类

    2018年google推出了bert模型,这个模型的性能要远超于以前所使用的模型,总的来说就是很牛.但是训练bert模型是异常昂贵的,对于一般人来说并不需要自己单独训练bert,只需要加载预训练模型, ...

  6. docker安装并运行redis

    拉取镜像: [mall@VM_0_7_centos ~]$ sudo docker pull redis:3.2 [sudo] password for mall: 3.2: Pulling from ...

  7. Qt编写气体安全管理系统26-组态设计

    一.前言 组态设计是应一个客户要求新增加进去的,设计理念就是在提供一个组态设计的初级功能,比如读取自定义控件动态库,加载所有的控件放到控件栏(有点类似qtcreator的控件栏)用户拖曳对应的控件到画 ...

  8. Laya的版本管理

    参考: Laya项目发布详解 发布时,勾选开启版本管理 点击上图“是否开启版本管理”右边的+号. 可以选择加入版本管理,或者排除版本管理的文件夹. 比如我要排除bin/test这个文件夹下的文件,不使 ...

  9. c-lodop回调函数简短问答及相关博文

    回调函数相关博文:C-Lodop回调函数的触发.LODOP.FORMAT格式转换[回调和直接返回值].Lodop导出excel及提示成功[回调和直接返回值].c-lodop获取任务页数-回调里给全局变 ...

  10. Survey of single-target visual tracking methods based on online learning 翻译

    基于在线学习的单目标跟踪算法调研 摘要 视觉跟踪在计算机视觉和机器人学领域是一个流行和有挑战的话题.由于多种场景下出现的目标外貌和复杂环境变量的改变,先进的跟踪框架就有必要采用在线学习的原理.本论文简 ...