Simple thread/mutex test application is crashing

869 views Asked by At

I wrote a simple test program which accumulates random samples to a buffer using multiple threads. Each thread uses a stack for reducing the mutex waits. This is for investigating problems in a much larger program.

The code currently crashes on mingw-w64 4.9.2

Any idea why?

Debugging halts on "signal-received" in a non-usable place (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

There are 1 answers

1
NathanOliver On BEST ANSWER

workers.clear(); is not going to join all of the threads. Calling clear() will call the threads' deconstructors. std::thread::~thread will call std::terminate() if the thread is joinable(). Since you are calling clear() on the vector right after you create the vector the threads are still processing and are joinable.

You have to join all threads manually before deleting them:

int main()
{
    // […]

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

    return 0;
}