1

My mistake is probably very obvious, but I cannot seem to figure it out... When running this, the Add and Subtract functions generate the same value when initiating new threads. If I am declaring a new variable everytime the function is called, why am i unable to generate different values at each invocation?

I have the following code,


#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <numeric>
#include <cmath>
#include <sstream>
#include <thread>
#include <chrono>
#include <ctime>
#include <mutex>

int GetRandom(int max){
    //generate a pseudo-random number with time as the seed
    //time as seed will always return a different starting point
    srand(time(NULL));
    //mod max to ensure we return a number below max
    return rand() % max;
}

std::string GetTime(){
    auto nowTime = std::chrono::system_clock::now();
    std::time_t sleepTime =
            std::chrono::system_clock::to_time_t(nowTime);
    return std::ctime(&sleepTime);
}

double acctBalance = 10;

// Protects shared data from being accessed at the
// same time
std::mutex acctLock;

void Add(int id,
        double adding, int sleep){
    int rand = GetRandom(10);

        std::cout <<"Add: "<<rand<< "\n";
    }
    // acctLock.unlock();


void Subtract(int id, double subtract, int sleep){
    int rand = GetRandom(10);
    std::cout <<"Subtract: "<<rand<< "\n";
    // acctLock.unlock();
}

int main()
{
    int rand = 3;


int count = 10;
std::vector<std::thread> threads;
threads.reserve(count);
for (size_t i = 0; i < count; i=i+2)
{
  threads.emplace_back(Add, i, 15,rand);
  threads.emplace_back(Subtract, i+1, 15,rand);
}
for (auto& thread : threads)
{
  thread.join();
}


    return 0;
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 4
    `srand(time(NULL));` Since, these functions are happening (practically) simultaneously, you are seeding the PRNG with the same value. – 001 Mar 11 '20 at 20:39
  • 4
    `srand()` doesn't belong anywhere, but once place, usually at the forefront of `main`. And you shouldn't be using it anyway; use `` instead. It, threading, and variadic templates, are the top three buckets of awesome and pure-win that were added to the language library almost a decade ago. – WhozCraig Mar 11 '20 at 20:43
  • 2
    I already [left a comment](https://stackoverflow.com/questions/60642150/how-can-i-create-a-variable-number-of-threads#comment107288100_60642150) in your previous question about this code warning you of this problem. [`srand()` — why call it only once?](https://stackoverflow.com/questions/7343833/srand-why-call-it-only-once) – François Andrieux Mar 11 '20 at 20:46
  • Well practically speaking you should never ever use srand in c++ anyhow, the problems are numerous. The distribution is now a bit less obviously bad, but that's it. – Voo Mar 12 '20 at 14:08

1 Answers1

4

srand() and rand() are not guaranteed to be thread-safe.

Use the stuff available in #include <random>

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79