一说到cocos2d-x,主要就是跨平台的特性,这篇就先说一下自己在多线程同步互斥上遇到的问题,完全使用同一套代码实现所有平台下的锁和信号量。
其中的P和V操作成一对使用,是阻塞型的信号量操作,即如果信号量的值小于等于零,则执行P操作的线程会被挂起,直到有其他线程执行V操作才会别唤醒,使用了互斥量和条件变量共同实现,类似于pthread的post和wait函数。而这里的post和wait是非阻塞的信号量操作,当信号量的值小于等于0时wait会返回false,否则返回true,这类似于pthread的post和try_wait函数。
一般来说,说到多线程和同步互斥,很多人都会想到使用pthread来实现,这样在win32平台下也只需要将pthread-for-win32安装并引入头文件即可,而我刚开始也是使用pthread,但发现iOS系统不支持匿名信号量,而有名信号量的使用中出了些问题,但是动态库中报错不会调试。恰好cocos2d-x 3是使用C++11标准写的,里面使用了很多C++11的新特性,而我也就学习了一下C++11的一些特性,发现其实C++11已经在std标准库中实现了多线程、互斥量(锁)与条件变量,但是并没有实现信号量,所以这里主要说用互斥量与条件变量实现阻塞等待与非阻塞等待的信号量,这样就可以完全抛开pthread了。
关于C++11 std互斥量和条件变量的使用可以直接搜索一下,有很多详细的教程,这里就直接贴出我的信号量的实现:
struct mySem
{
public:
int sem_num;
std::mutex semLock;
std::condition_variable cv;
bool ready;
mySem() : sem_num(0), ready(false) {}
void P()
{
std::unique_lock<std::mutex> lock(semLock);
while(!ready)
cv.wait(lock);
sem_num--;
if(sem_num <= 0)
ready = false;
}
void V() {
std::unique_lock<std::mutex> lock(semLock);
sem_num++;
if(sem_num > 0)
{
ready = true;
cv.notify_one();
}
}
bool wait()
{
std::lock_guard<std::mutex> lock(semLock);
if(sem_num <= 0)
return false;
else
{
sem_num--;
return true;
}
}
void post()
{
std::lock_guard<std::mutex> lock(semLock);
sem_num++;
}
}
其中的P和V操作成一对使用,是阻塞型的信号量操作,即如果信号量的值小于等于零,则执行P操作的线程会被挂起,直到有其他线程执行V操作才会别唤醒,使用了互斥量和条件变量共同实现,类似于pthread的post和wait函数。而这里的post和wait是非阻塞的信号量操作,当信号量的值小于等于0时wait会返回false,否则返回true,这类似于pthread的post和try_wait函数。
嗯,就先这么多啦,用起来还算好,虽然本人太菜,没有加任何的容错机制,但用起来还算不错。