When I generate the random number with single thread, no duplicate in 4M uuids generated but if I generate with two threads each 1M, I see roughly 16-20 duplicates. What could be the reason?
class TestUuid
{
public:
std::string GenerateUUid(){
boost::uuids::uuid uid;
{
boost::mutex::scoped_lock(m_mRandomGen);
uid = m_oRandomGen();
}
std::stringstream ss;
ss << uid;
return ss.str();
}
void TestUid(std::map<std::string, unsigned>& mUids, unsigned count){
for(unsigned i = 0; i < count; ++i) {
std::string sUid = GenerateUUid();
std::map<std::string, unsigned>::const_iterator it = mUids.find(sUid);
if(it == mUids.end()){
mUids[sUid] = i;
}else {
std::cerr << "Duplicate uid:" << sUid << " found in thread id:" << pthread_self() << ", counter:" << i << ", earlier counter:" << it->second << ", id:" << it->first<< std::endl;
}
}
}
TestUnique() {
unsigned count = 4000000;
std::map<std::string, unsigned> uuids;
TestUid(uuids, count);
}
TestUniqueMultiThread() {
unsigned count = 1000000;
std::map<std::string, unsigned> mUids1;
boost::thread t1(boost::bind(&TestUuid::TestUid, this, mUids1, count));
std::map<std::string, > Uunsignedids2;
boost::thread t2(boost::bind(&TestUuid::TestUid, this, mUids2, count));
t1.join();
t2.join();
}
private:
boost::mutex m_mRandonGen;
boost::uuids::random_generator m_oRandomGen;
}
int main() {
TestUid oTest;
oTest.TestUnique(); //work fine. no duplicate in 4M uuids
oTest.TestUniqueMultiThread(); // around 16-20 duplicates in total 2*1M = 2M uuids
return EXIT_SUCCESS;
}
below is the log.
Duplicate uid:9f4bfa5c-8e41-4012-ba3e-0b3e631834dc found in thread id:1103669568, counter:12016, earlier counter:12015, id:9f4bfa5c-8e41-4012-ba3e-0b3e631834dc Duplicate uid:0237b010-cb8f-4b89-9f47-042722902883 found in thread id:1103669568, counter:65778, earlier counter:65777, id:0237b010-cb8f-4b89-9f47-042722902883 Duplicate uid:7a999ce7-0936-4642-b796-485334fc6ba4 found in thread id:1093179712, counter:170570, earlier counter:170568, id:7a999ce7-0936-4642-b796-485334fc6ba4 Duplicate uid:09e1028b-5fc9-4fcd-ab70-991c02d47aec found in thread id:1093179712, counter:208740, earlier counter:208739, id:09e1028b-5fc9-4fcd-ab70-991c02d47aec Duplicate uid:66eb72f5-a3de-4941-8a64-6dad773f0ffb found in thread id:1093179712, counter:211449, earlier counter:211448, id:66eb72f5-a3de-4941-8a64-6dad773f0ffb Duplicate uid:8bccb459-1e70-4920-8486-6b0c5dcb3992 found in thread id:1093179712, counter:212972, earlier counter:212971, id:8bccb459-1e70-4920-8486-6b0c5dcb3992 Duplicate uid:bb8109e3-6529-4122-a015-a9746900f692 found in thread id:1093179712, counter:239296, earlier counter:239295, id:bb8109e3-6529-4122-a015-a9746900f692 Duplicate uid:a02ea282-b49b-4e4f-98a3-01406824c888 found in thread id:1103669568, counter:338582, earlier counter:338581, id:a02ea282-b49b-4e4f-98a3-01406824c888 Duplicate uid:8bc848d7-bbe9-405c-9ef3-4d5ec312aa5e found in thread id:1093179712, counter:472035, earlier counter:472010, id:8bc848d7-bbe9-405c-9ef3-4d5ec312aa5e Duplicate uid:d3d8e09f-c410-4ce0-9a75-2a0c363db89c found in thread id:1093179712, counter:531441, earlier counter:531440, id:d3d8e09f-c410-4ce0-9a75-2a0c363db89c Duplicate uid:3130184f-345e-4d1c-bb01-d481eec29704 found in thread id:1093179712, counter:548770, earlier counter:548769, id:3130184f-345e-4d1c-bb01-d481eec29704 Duplicate uid:29572641-2487-400a-926f-9bbf7ca176b4 found in thread id:1093179712, counter:710813, earlier counter:710811, id:29572641-2487-400a-926f-9bbf7ca176b4 Duplicate uid:36b3567d-5f06-4c72-a395-e6f6ce056c6b found in thread id:1093179712, counter:728598, earlier counter:728597, id:36b3567d-5f06-4c72-a395-e6f6ce056c6b Duplicate uid:3290cb7e-2535-43bc-b53c-71ac0bc4fca1 found in thread id:1103669568, counter:846883, earlier counter:846881, id:3290cb7e-2535-43bc-b53c-71ac0bc4fca1 Duplicate uid:59137657-2b2a-473e-b12c-1890d6058ca2 found in thread id:1093179712, counter:814812, earlier counter:814810, id:59137657-2b2a-473e-b12c-1890d6058ca2
This is a common error when using RAII locks: you forgot to give your lock a name in the line
so it didn't lock anything at all. Change it to
EDIT: what really happened: There was no compiler error despite the typo in the mutex name because the declaration
is the same as
if the name has not been declared before. In other words, you've default-constructed a new
scoped_lock
calledm_mRandomGen
, not associated with a mutex.