简单的线程/互斥测试应用程序正在崩溃

时间:2015-06-16 16:59:34

标签: c++ multithreading c++11 mutex mingw-w64

我编写了一个简单的测试程序,它使用多个线程将随机样本累积到缓冲区。每个线程使用一个堆栈来减少互斥锁等待。 这是为了在更大的计划中调查问题。

代码目前在mingw-w64 4.9.2

上崩溃

知道为什么吗?

调试在不可用的地方停止“收到信号”(ntdll!DbgBreakPoint)

#include <iostream>
#include <vector>
#include <random>
#include <thread>
#include <mutex>
#include <cstdint>


//The function which will be run concurrently in several threads
void work(float * buf, uint64_t * ns, std::mutex * mtx)
{
    std::mt19937 generator;
    std::uniform_real_distribution<double> distrib(0., 1.);
    std::vector<float> stack;
    unsigned int stackPos = 0;

    for(unsigned int i=0;i<1000000;i++)
    {
        //Generate a random sample uniformly between 0 and 1
        double sample = distrib(generator);

        //Append the sample to the stack
        if(stackPos>=stack.size())
        {
            stack.resize(stackPos+1);
        }
        stack[stackPos] = sample;
        ++stackPos;

        //Try to acquire the accumulation buffer
        bool locked = mtx->try_lock();

        //Force aquire if the stack is too large and if try_lock failed
        if(!locked && stackPos>2000)
        {
            mtx->lock();
            locked = true;
        }

        //If the buffer lock is aquired, flush the stack
        if(locked)
        {
            for(unsigned int i=0;i<stackPos;i++)
            {
                *buf += stack[i];
                *ns = *ns + 1;
            }
            stackPos = 0;
            //And unlock
            mtx->unlock();
        }

    }
}


int main()
{
    float buffer = 0;
    uint64_t numSamples = 0;
    std::mutex mtx;

    //Start a couple of parallel threads
    std::vector<std::thread> workers;
    for(unsigned int i=0;i<16;i++)
    {
        workers.emplace_back(std::thread(work, &buffer, &numSamples, &mtx));
    }

    //This will join the threads
    workers.clear();


    std::cout << "Average : " << buffer/numSamples << std::endl;
    return 0;
}

1 个答案:

答案 0 :(得分:4)

workers.clear();不会加入所有线程。调用clear()将调用线程的解构器。如果帖子为std::thread::~thread,则std::terminate()会调用joinable()。由于您在创建向量后立即在向量上调用clear(),因此线程仍在处理并且可以连接。

在删除之前,您必须手动加入所有线程:

int main()
{
    // […]

    //This will join the threads
    for (std::thread& thread : workers)
    {
        thread.join();
    }
    workers.clear();

    return 0;
}