多个线程同时访问共享资源时,经常会出现冲突等。为了避免这种情况的发生,可以使用互斥量,当一个线程锁住了互斥量后,其他线程必须等待这个互斥量解锁后才能访问它。

thread提供了四种不同的互斥量:

1、独占式互斥量non-recursive (std::mutex)

  独占式互斥量加解锁是成对的,同一个线程内独占式互斥量在没有解锁的情况下,再次对它进行加锁这是不对的,会得到一个未定义行为。

2、递归式互斥量recursive (std::recursive_mutex)

  与独占式互斥量不同的是,同一个线程内在互斥量没有解锁的情况下可以再次进行加锁,不过他们的加解锁次数需要一致,递归式互斥量我们平时可能用得比较少些。

3、允许超时的独占式互斥量non-recursive that allows timeouts on the lock functions(std::timed_mutex)

     用法同独占式互斥量,如果线程1对共享资源的访问时间比较长,这时线程2可能等不了那么久,所以设置一个超时时间,在到了超时时间时如果线程1中的互斥量还没有解锁,线程2就不等了,继续往下执行。

4、允许超时的递归式互斥量recursive mutex that allows timeouts on the lock functions (std::recursive_timed_mutex)

 

下面以外卖为例演示下互斥量和线程锁的用法:假如有50份蛋炒饭,两个下单窗口同时运作,蛋炒饭卖完为止。


代码实操:

头文件:

#ifndef __TestMutex_SCENE_H__
#define __TestMutex_SCENE_H__ #include "cocos2d.h" USING_NS_CC; class TestMutex : public cocos2d::Layer
{
int total;//总量
int selled;//卖出量
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(TestMutex); void threadA();
void threadB();
}; #endif // __TestMutex_SCENE_H__

源文件:

#include "TestMutex.h"
#include <thread> std::mutex _mutex;
Scene* TestMutex::createScene()
{
auto scene = Scene::create();
auto layer = TestMutex::create();
scene->addChild(layer);
return scene;
} bool TestMutex::init()
{
if ( !Layer::init() )
{
return false;
} total = 50;
selled = 0; std::thread t1(&TestMutex::threadA,this);
t1.detach(); std::thread t2(&TestMutex::threadB,this);
t2.detach(); return true;
}
void TestMutex::threadA()
{
while (selled<total)
{
// 加锁
_mutex.lock();
selled++;
std::this_thread::sleep_for(std::chrono::seconds(3));
log("threadA %d",selled);
// 解锁
_mutex.unlock();
}
} void TestMutex::threadB()
{
while (selled<total)
{
_mutex.lock();
selled++;
std::this_thread::sleep_for(std::chrono::seconds(3)); log("threadB %d",selled);
_mutex.unlock();
}
}
05-08 08:19