Cocos2dx 3.0 过渡篇(二十七)C++11多线程std::thread的简单使用(下)
本篇接上篇继续讲:上篇传送门:http://blog.csdn.net/star530/article/details/24186783
简单的东西我都说的几乎相同了,想挖点深的差点把自己给填进去。
以下实际演练一下。请同意我參考偶尔E往事的一篇线程的博客, 他用的是pThread。这里我就用std::thread。
1.售票
孙鑫老师的C++和Java多线程售票也一直让我念念不忘(好吧,我承认我没看过)。这里用cocos2d-x3.0和C++11的std::thread实现一个吧。总共同拥有100张诺亚方舟船票。有2个售票点A和B在售票(一张票就一百亿美元吧)。当票卖完了就结束了。我们知道当程序一開始进程就会创建一个主线程,所以能够在主线程基础上再创建2个线程A和B,再线程A和B中分别售票,当票数为0的时候,结束线程A和B。
2.多线程售票,代码例如以下:
//HelloWorld.h
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init(); CREATE_FUNC(HelloWorld); void myThreadA();//线程A
void myThreadB();//线程B int tickets;//票数 }; //.cpp
bool HelloWorld::init()
{
if ( !Layer::init() )
{
return false;
} tickets = 100;//100张票 std::thread tA(&HelloWorld::myThreadA,this);//创建一个分支线程,回调到myThread函数里
std::thread tB(&HelloWorld::myThreadB,this);
tA.detach();
tB.detach();
// t1.detach(); CCLOG("in major thread");//在主线程
return true;
} void HelloWorld::myThreadA()
{
while(true)
{
if(tickets>0)
{
Sleep(10);
CCLOG("A Sell %d",tickets--);//输出售票。每次减1
}
else {
break;
}
}
}
void HelloWorld::myThreadB()
{
while(true)
{
if (tickets>0)
{
Sleep(10);
CCLOG("B Sell %d",tickets--);
}
else
{
break;
}
}
}
代码非常easy。不多说了。我们来看一下输出。会发现有非常多喜闻乐见的现象出现。由于每一个人每次执行的结果都不一样。所以这里不贴结果了,当中比較有意思的现象是同一张票卖了两次?!
原因不多解释了,时间片的问题,不明确的Google之。
假设你认为不会有这么巧,那么在打印结果前加上这么一句:
Sleep(100);
执行结果如图所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3RhcjUzMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
3.利用相互排斥对象同步数据
这个问题主要是由于一个线程执行到一半的时候,时间片的切换导致还有一个线程改动了同一个数据,当再次切换会原来线程并继续往下执行的时候,数据由于被改动了导致结果出错。
所以我们要做的就是保证这个线程全然执行完。所以对线程加锁是个不错的注意,相互排斥对象mutex就是这个锁。
3.1、初始化相互排斥锁
std::mutex mutex;//线程相互排斥对象
3.2、改动myThreadA与myThreadB的代码,在里面加入相互排斥锁
void HelloWorld::myThreadA()
{
while(true)
{
mutex.lock();//加锁
if(tickets>0)
{
Sleep(10);
CCLOG("A Sell %d",tickets--);//输出售票。每次减1
mutex.unlock();//解锁
}
else {
mutex.unlock();
break; }
}
}
void HelloWorld::myThreadB()
{
while(true)
{
mutex.lock();
if (tickets>0)
{
Sleep(10);
CCLOG("B Sell %d",tickets--);
mutex.unlock();
}
else
{
mutex.unlock();
break;
}
}
}
执行结果例如以下。完美
使用std::mutex有一个要注意的地方:在线程A中std::mutex使用成员函数lock加锁unlock解锁,看起来工作的非常好,但这样是不安全的,你得始终记住lock之后一定要unlock。可是假设在它们中间出现了异常或者线程直接退出了unlock就没有执行,由于这个相互排斥量是独占式的。所以在threadA没有解锁之前,其它使用这个相互排斥量加锁的线程会一直处于等待状态得不到执行
恩,就写到这里。
嘿嘿嘿嘿。
尊重原创,转载请注明来源:http://blog.csdn.net/star530/article/details/24187103
Cocos2dx 3.0 过渡篇(二十七)C++11多线程std::thread的简单使用(下)的更多相关文章
- Cocos2dx 3.0 过渡篇(二十六)C++11多线程std::thread的简单使用(上)
昨天练车时有一MM与我交替着练,聊了几句话就多了起来,我对她说:"看到前面那俩教练没?老色鬼两枚!整天调戏女学员."她说:"还好啦,这毕竟是他们的乐趣所在,你不认为教练每 ...
- Cocos2dx 3.0 过渡篇(三十)灰机还是3D好(Sprite3D)
如今都非常少发3.0过渡篇这一系列的博文了,原因是多方面的,一个是游戏开发进度,尽管上面并没给我什么压力,但我自己一直在赶.还有一方面是个人私生活这块.五月份确实是多事之秋,有时候真的没办法全心思去研 ...
- Cocos2dx 3.0 过渡篇(二十八)C++11强类型枚举
一朋友在微信朋友圈晒了张照片,随手点开大图,带着赞赏的眼光扫了下,恩,几个月不见.又美丽了...咦?等等,她戴的这是什么?酷炫的造型! 金属边框! 微型摄像头! 这不是传说中的谷歌眼镜么?土豪啊,还好 ...
- Cocos2dx 3.0 过渡篇(三十一)ValueVector和Vector不得不说的故事
本文投票地址:http://vote.blog.csdn.net/Article/Details?articleid=37834689 前天看到一个颇为纠结的选择题:有一天你遇到一个外星人,这时外星人 ...
- Cocos2dx 3.0 过渡篇(二十九)globalZOrder()与localZOrder()
前天非常难得的加班到八点...为什么说难得呢?由于平时我差点儿就没加班过.六点下班后想走就走,想留就留.率直洒脱.不拘一格.尽显男儿本色.程序猿,就是这么自信! -----------这篇博客的标题本 ...
- Cocos2dx 3.0 过渡篇(二十五)死不了的贪食蛇(触摸版)
上一篇写的贪食蛇的重力感应控制版,这一篇就讲下触摸控制版吧.额,也不知道写了那个贪食蛇教程究竟有没有获得沈老师的书,假设没有的话,看我不拿西瓜刀砍掉 偶尔E往事 的那啥! 重力版链接:http://b ...
- Cocos2dx 3.0 交流篇
创建项目: For(MAC) Runtime Requirements Android 2.3 or newer iOS 5.0 or newer OS X 10.7 or newer Windows ...
- Cocos2dx3.0过渡篇 各种遍历与范围for语句的使用【转】
1.CCArray的遍历看到这里,有些人又按耐不住的要举起西瓜刀了:你不是说3.0beta后已经没有CCArray这货了吗?现在又拿出来作甚?其实我也很无辜,CCArray确实是没了,但在某个不为人知 ...
- Cocos2dx3.0过渡篇 globalZOrder()与localZOrder()
这篇博客的标题本想叫“...3.0新的渲染...介绍”,最后还是拉不下这个脸.为啥?觉得自己对渲染的认识还是过于表面,谈不上理解.当然了,这并不影响这篇博客继续写下去.下面看一段3.0Release ...
随机推荐
- 8-12 Erratic Expansion uva12627
题意:一开始有一个红气球 每小时后一个红气球会变成三个红气球和一个蓝气球 第k小时 a到b行之间有几个红气球 递归找规律题目 一定要注意涉及指数的时候一定要开long long 数组!!!! #i ...
- poj1847 Tram(Dijkstra || Floyd || SPFA)
题目链接 http://poj.org/problem?id=1847 题意 有n个车站,编号1~n,每个车站有k个出口,车站的出口默认是k个出口中的第一个,如果不想从默认出口出站,则需要手动选择出站 ...
- mysql 解除正在死锁的状态
转自:http://blog.csdn.net/hotdust/article/details/51524469 from: http://www.2cto.com/database/201303/1 ...
- Emacs 编辑verilog 学习日记
终于开始写博客啦.以前一直打算写.由于工作忙一次次延期了.写博客的好处不必多说. 以前有一些学习心得总是用一个word,或者note记录一些.时间久了都不知道弄哪儿去了.. 从今天开始记录学习中 ...
- Python 编程:从入门到实战 读书笔记
1..title() 每个单词首字母大写 .upper() 所有字母大写 .lower() 所有字母小写 2. \t 空白 转义字符只能用在""内 ...
- C++运算符重载 模板友元 new delete ++ = +=
今天的重载是基于C++ 类模板的,如果需要非类模板的重载的朋友可以把类模板拿掉,同样可以参考,谢谢. 一.类模板中的友元重载 本人喜好类声明与类成员实现分开写的代码风格,如若您喜欢将类成员函数的实现写 ...
- JQuery基础-DAY1
jQuery介绍 是一个轻量级的js框架/库,其宗旨是write less do more. jQuery对象 js的对象叫做dom对象 使用jQuery框架产生的对象是jQuery对象,是对dom对 ...
- Revit二次开发示例:AutoStamp
该示例中,在Revit启动时添加打印事件,在打印时向模型添加水印,打印完成后删除该水印. #region Namespaces using System; using System.Collect ...
- softmax为什么使用指数函数?(最大熵模型的理解)
解释1: 他的假设服从指数分布族 解释2: 最大熵模型,即softmax分类是最大熵模型的结果. 关于最大熵模型,网上很多介绍: 在已知部分知识的前提下,关于未知分布最合理的推断就是符合已知知识最不确 ...
- C# CuttingEdge.Conditions 验证帮助类库 文档翻译
项目主页: https://archive.codeplex.com/?p=conditions 作者博客关于项目的文档(翻译原文): https://www.cuttingedge.it/blogs ...