使用线程的意外行为

时间:2015-07-08 09:40:13

标签: c++ multithreading

我有一个功能,我想通过多线程优化。试图使用RenderBodiesBodypBodies对象的整个向量调用函数RenderBodies(pBodies); ,因为我喜欢这样:

pBodies

我想称之为4次,每次使用std::vector<Body*> Bodies1, Bodies2, Bodies3, Bodies4; for (unsigned int i = 0; i < pBodies.size(); i += 4) { Bodies1.push_back(pBodies[i]); Bodies2.push_back(pBodies[i + 1]); Bodies3.push_back(pBodies[i + 2]); Bodies4.push_back(pBodies[i + 3]); } 向量的不同四分之一,并且并行运行它们。

所以我将这样的矢量分开:

std::thread t1(RenderBodies, pTarget, Bodies1, pZoom);
std::thread t2(RenderBodies, pTarget, Bodies2, pZoom);
std::thread t3(RenderBodies, pTarget, Bodies3, pZoom);
std::thread t4(RenderBodies, pTarget, Bodies4, pZoom);

t1.join();
t2.join();
t3.join();
t4.join();

然后使用带有新向量的线程

RenderBodies(pTarget, Bodies1, pZoom);
RenderBodies(pTarget, Bodies2, pZoom);
RenderBodies(pTarget, Bodies3, pZoom);
RenderBodies(pTarget, Bodies4, pZoom);

但结果是没有渲染。

问题是,RenderBodies函数没有任何问题,因为如果我试着使用它:

sf::RectangleShape Temp;

    mtx.lock();
    for (unsigned int i = 0; i < param.pBodies.size(); i++)
    {
        if (param.pZoom > 1)
            Temp.setSize(sf::Vector2f(param.pBodies.at(i)->mass * param.pZoom, param.pBodies.at(i)->mass * param.pZoom));
        else
            Temp.setSize(sf::Vector2f(param.pBodies.at(i)->mass, param.pBodies.at(i)->mass));

        float AccelCoefficient = static_cast<float> (sqrt(param.pBodies.at(i)->AccelX * param.pBodies.at(i)->AccelX + param.pBodies.at(i)->AccelY * param.pBodies.at(i)->AccelY) * (20000 * _GRAV_CONST));

        if (AccelCoefficient > 1)
            AccelCoefficient = 1;

        float Red, Green, Blue;

        Blue = 1 - (AccelCoefficient);

        if (AccelCoefficient < 0.2)
            Red = (AccelCoefficient)* 5;
        else
            Red = 1;

        if (AccelCoefficient < 0.5)
            Green = (AccelCoefficient)* 2;
        else
            Green = 1;

        Temp.setFillColor(sf::Color(static_cast<sf::Uint8> (Red * 255), static_cast<sf::Uint8> (Green * 255), static_cast<sf::Uint8> (Blue * 255), 128));

        Temp.setPosition(static_cast<float>(param.pBodies.at(i)->posX), (static_cast<float>(param.pBodies.at(i)->posY)));

        param.pTarget->draw(Temp);
    }
    mtx.unlock()

有效!但它没有使用我的cpu的所有4个核心,所以它没用。

为什么线程没有按预期工作?

我在RenderBodies()中的代码:

No,BundleNo,Grossweight,Pieces,Tareweight,Netweight
1,Q4021317/09,193700,1614,646,193054
2,Q4021386/07,206400,1720,688,205712

1 个答案:

答案 0 :(得分:2)

在不知道RenderBodies()功能正在做什么的情况下,无法给出准确的答案。

但是,我的猜测是它与参数pTarget相关,其中相同的值被传递给所有线程,并且(从名称)是一个指针。如果是这样,这意味着您有四个线程与一个对象交互 - 因此线程必须同步它们对该对象的访问(例如,使用互斥或​​临界区)。

如果线程除了呈现pTarget之外没有做太多的事情,同步对它的访问将否定多线程的大多数好处(因为,实际上,这会导致所有线程彼此等待并且所有渲染都是连续的。)

但是,这就是它的方式。多线程不是免费的午餐。获得性能的方法是最小化线程之间的同步(即使它们彼此等待)。如果你不这样做,你就会遇到竞争条件,因此操作可能无法正确完成 - 这就是你所描述的内容。

这就是为什么一个用户界面设计指南通常只有一个线程负责渲染窗口/屏幕。