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" />

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

时间: 2024-10-01 12:56:49

Cocos2dx 3.0 过渡篇(二十七)C++11多线程std::thread的简单使用(下)的相关文章

Cocos2dx 3.0 过渡篇(二十九)globalZOrder()与localZOrder()

前天很难得的加班到八点...为什么说难得呢?因为平时我几乎就没加班过.六点下班后想走就走,想留就留.率直洒脱,不拘一格,尽显男儿本色.程序员,就是这么自信! -----------这篇博客的标题本想叫"...3.0新的渲染...介绍",最后还是拉不下这个脸.为啥?觉得自己对渲染的认识还是过于表面,谈不上理解.当然了,这并不影响这篇博客继续写下去.下面看一段3.0Release Notes 对于新渲染器的一段介绍: Node 增加了新的函数 setGlobalZOrder() / get

Cocos2dx 3.0 过渡篇(二十八)C++11强类型枚举

一朋友在微信朋友圈晒了张照片,随手点开大图,带着欣赏的眼光扫了下,恩,几个月不见,又漂亮了...咦?等等,她戴的这是什么?酷炫的造型!金属边框!微型摄像头!这不是传说中的谷歌眼镜么?土豪啊,还好我们已经是朋友了...我先给了她一个赞,然后直奔主题,霸气回复道:我过几天去找你,你戴的是谷歌眼镜吧,哼哼小样,不想死的话...就让我...摸一下下可以么,我不奢求戴,摸一下就满足了...(哎,丢人啊). ------------------- 在cocos2dx 3.0的文档里有这么一句话:以 k 开头

Cocos2dx 3.0 过渡篇(三十一)ValueVector和Vector不得不说的故事

本文投票地址:http://vote.blog.csdn.net/Article/Details?articleid=37834689 前天看到一个颇为纠结的选择题:有一天你遇到一个外星人,这时外星人很热情的邀请你到他们星球去玩,你如何选 1:去,但是你有可能永远不能在回来.2:不去,但是外星人会消去你的记忆 这问题很刺激有木有?!看似简单的一个问题,不同的答案却隐藏着不同的含义.------------------鱼与熊掌不可兼得,类似这种例子生活中会经常碰到.同样的,如果你有去了解过Coco

Cocos2dx 3.0 过渡篇(二十五)死不了的贪食蛇(触摸版)

上一篇写的贪食蛇的重力感应控制版,这一篇就讲下触摸控制版吧.额,也不知道写了那个贪食蛇教程究竟有没有获得沈老师的书,假设没有的话,看我不拿西瓜刀砍掉 偶尔E往事 的那啥! 重力版链接:http://blog.csdn.net/start530/article/details/23707985 触摸版与重力版的代码大部分都一样,不一样的地方就是要将打开重力感应换成创建一个触摸监听.步骤例如以下: 1.在GameLayer的init()中创建一个触摸监听事件 [cpp] view plaincopy

Cocos2dx 3.0 过渡篇(三十二)话说ValueMap的一般使用

周末到厦门找死党聚聚,晚上一伙人杀到一还算凑合的大排档准备来个不醉不归.菜都点完了朋友突然说这里没有洗手间...尼玛,当时我们就不乐意了:喝五六个小时的啤酒,没有洗手间你是打算憋死谁?二话不说直接换一家,不过这次一定要谨慎选择,最终看到一家看起来还算正宗的大排档,我下意识拨了下头发,走到前台MM面前,轻声问道:你们这...有洗手间吗? 声音低沉且性感,语调中还夹带着些许的忧伤. 前台MM瞪大眼睛,好一会才反应过来说道:洗手间?肯定有啊! ----------------------------

Cocos2dx3.0过渡篇 各种遍历与范围for语句的使用【转】

1.CCArray的遍历看到这里,有些人又按耐不住的要举起西瓜刀了:你不是说3.0beta后已经没有CCArray这货了吗?现在又拿出来作甚?其实我也很无辜,CCArray确实是没了,但在某个不为人知的角落里却藏着__Array这货,我大胆猜测它是CCArray同父异母的兄弟,因为它有着和CCArray一样的功能.可惜的是,因为Vector的崛起,__Array注定只会埋没. CCArray的遍历宏是CCARRAY_FOREACH(_array,_object),这种遍历方式是正想遍历,用for

关于Cocos2d-x 3.0正式版 粒子问题在IOS上正常显示,在Android下有问题的解决方式

前几个在Cocos2d-x论坛上,有人提到粒子系统的问题..这里列举一下解决的方法: 或许到时候大家用粒子效果的时候也会发现这个问题,如今把这个问题的解决办法说出来.至于原因我也不知道是引擎的问题还是个人的问题,在用Xcode进行开发的时候IOS跟Mac天生对游戏的Z轴不敏感,你怎么用Z轴都没关系.甚至不用设置都OK,可是编译到了Android平台就不行了,也不知道引擎内部是什么原理,在Android天生对Z轴敏感.这个问题非常难描写叙述,也非常难理解. (PS:原因就是添加子对象的Z轴关系要处

Cocos2d-x 3.0的启动流程

Cocos2d-x 3.0变动很大,包括启动的方式,我看了下对android的启动总结如下: Java方面: AppActivity继承Cocos2dxActivity Cocos2dxActivity的onCreate函数中加载本地.so 加载.so的时候会统一到javaactivity.cpp里面寻找JNI_OnLoad等本地接口,来运行本地文件 其中Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit会cocos2d::Application:

从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十七 ║Vue基础:给博客首页加花样(二)

回顾 今天来晚辣,给公司做了一个小项目,一个瀑布流+动态视频控制的DEMO,有需要的可以联系我,公司的项目就不对外展示了(一个后端程序员真的要干前端了哈哈哈). 书接上文,昨天正式的开始了Vue的代码的学习,简单的通过一些假的数据来展示了下个人博客的首页列表,不知道大家是否还记得昨天讲的什么,如果不太清楚呢,可以再回顾下<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十七 ║Vue基础:使用Vue.js 来画博客首页(一)>,我们主要说到了,Vue的核心语法是什么,MVVM