c++ - 多个线程访问共享资源

标签 c++ multithreading c++11 opengl sdl

我目前正在开发一个粒子系统,该系统使用一个线程,其中粒子首先更新,然后绘制。粒子存储在 std::vector 中。我想将更新功能移至单独的线程以提高系统性能。然而,这意味着当更新线程和绘制线程同时访问 std::vector 时我会遇到问题。我的更新函数更改所有粒子的位置值和颜色,并且几乎总是调整std::vector的大小。

单线程方法:

std::vector<Particle> particles;
void tick() //tick would be called from main update loop
{
    //slow as must wait for update to draw
    updateParticles();
    drawParticles();
}

多线程:

std::vector<Particle> particles;
//quicker as no longer need to wait to draw and update
//crashes when both threads access the same data, or update resizes vector
void updateThread()
{
    updateParticles();
}
void drawThread()
{
    drawParticles();
}

为了解决这个问题,我使用 std::mutex 进行了研究,但在实践中,如果有大量粒子,线程的持续锁定意味着性能不会提高。我还研究了 std::atomic ,但是粒子和 std::vector 都不是可简单复制的,因此也不能使用它。

使用互斥体的多线程:

注意:我正在使用 SDL 互斥体,据我所知,原理是相同的。

SDL_mutex mutex = SDL_CreateMutex();
SDL_cond canDraw = SDL_CreateCond();
SDL_cond canUpdate = SDL_CreateCond();
std::vector<Particle> particles;
//locking the threads leads to the same problems as before, 
//now each thread must wait for the other one
void updateThread()
{
    SDL_LockMutex(lock);
    while(!canUpdate)
    {
        SDL_CondWait(canUpdate, lock);
    }
    updateParticles();
    SDL_UnlockMutex(lock);
    SDL_CondSignal(canDraw);
}
void drawThread()
{
    SDL_LockMutex(lock);
    while(!canDraw)
    {
        SDL_CondWait(canDraw, lock);
    }
    drawParticles();
    SDL_UnlockMutex(lock);
    SDL_CondSignal(canUpdate);
}

我想知道是否还有其他方法可以实现多线程方法?本质上是防止两个线程同时访问相同的数据,而不必让每个线程等待另一个线程。我曾考虑过制作要从中绘制的 vector 的本地拷贝,但这似乎效率低下,并且如果更新线程在复制 vector 时更改 vector ,可能会遇到相同的问题?

最佳答案

我会使用更细粒度的锁定策略。我不会在您的 vector 中存储粒子对象,而是存储一个指向不同对象的指针。

结构锁定粒子{ 粒子*包含的粒子; SDL_mutex 锁定对象; };

updateParticles() 中,我将尝试使用 SDL_TryLockMutex() 获取各个锁定对象 - 如果我无法获得互斥体的控制权,我会将指针添加到将此特定的 lockedParticle 实例复制到另一个 vector ,并稍后重试更新它们。

我会在drawParticles()中遵循类似的策略。这依赖于这样一个事实:绘制顺序对于粒子来说并不重要,这种情况经常发生。

关于c++ - 多个线程访问共享资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43697618/

相关文章:

c++ - 安全使用 std::tmpnam

c# - 线程中的 powershell/runspace

c++通过csv文件和最后一列进行解析

c++ - 为什么 clang 和 gcc 在这个虚拟继承代码上意见不一?

c++ - 如何为模板类的 const ref 成员定义 move 赋值运算符

c++ - 什么是std::mutex阻止线程修改?

c++ - 在 C++ 中使用 <elem> 对函数

c++ - 线程间同步

java - Android - 使用位图的 AsyncTask - OutOfMemoryError

c - 如果我们需要按特定顺序打印多线程计算的结果,为什么信号而不是广播有效?