提高:: ::的UUID和random_generator独特多线程 [英] boost::uuids::random_generator and uniqueness with multiple threads
问题描述
当我生成单个线程随机数,产生的UUID在4M没有重复的,但如果我有两个线程每1M产生,我看到大约16-20重复。可能是什么原因呢?
类TestUuid
{
上市:
标准::字符串GenerateUUid(){
提高:: UUID的UUID :: UID;
{
提高::互斥:: scoped_lock中(m_mRandomGen);
UID = m_oRandomGen();
}
的std :: stringstream的SS;
SS<< UID;
返回ss.str();
}
无效TestUid(性病::地图<的std ::字符串,无符号>&安培; mUids,无符号数){
对(无符号I = 0; I<计数; ++ I){
标准::字符串SUID = GenerateUUid();
性病::地图<的std ::字符串,无符号> ::为const_iterator吧= mUids.find(SUID);
如果(它== mUids.end()){
mUids [SUID] =我;
}其他{
的std :: CERR<< 重复UID:<< SUID<< 在线程ID找到:<< pthread_self()&所述;&下; 柜台:<< I<< 前面柜台:<< IT->第二个<< ID:<<它 - >首先<<的std :: ENDL;
}
}
} TestUnique(){
无符号数= 4000000;
性病::地图<的std ::字符串,无符号>的UUID;
TestUid(的UUID,计数);
} TestUniqueMultiThread(){
无符号数= 1000000;
性病::地图<的std ::字符串,无符号> mUids1;
提高::线程T1(的boost ::绑定(安培; TestUuid :: TestUid,为此,mUids1,计数)); 性病::地图<的std ::字符串> Uunsignedids2;
提高::线程T2(的boost ::绑定(安培; TestUuid :: TestUid,为此,mUids2,计数));
t1.join();
t2.join();
} 私人的:
提高::互斥m_mRandonGen;
提高:: UUID的:: random_generator m_oRandomGen;}诠释主(){
TestUid oTest;
oTest.TestUnique(); //做工精细。在4M的UUID没有重复
oTest.TestUniqueMultiThread(); // 16-20左右重复,共有2 * 1M = 2M的UUID
返回EXIT_SUCCESS;
}
下面是日志。
相同的UID:在线程ID发现9f4bfa5c-8e41-4012-ba3e-0b3e631834dc:1103669568,柜台:12016,前面柜台:12015,ID:9f4bfa5c-8e41-4012-ba3e-0b3e631834dc
相同的UID:0237b010-cb8f-4b89-9f47-042722902883的线程ID发现:1103669568,柜台:65778,前面柜台:65777,ID:0237b010-cb8f-4b89-9f47-042722902883
相同的UID:7a999ce7-0936-4642-b796-485334fc6ba4的线程ID发现:1093179712,计数器:170570,先前计数器:170568,ID:7a999ce7-0936-4642-b796-485334fc6ba4
相同的UID:09e1028b-5fc9-4fcd-ab70-991c02d47aec的线程ID发现:1093179712,计数器:208740,先前计数器:208739,ID:09e1028b-5fc9-4fcd-ab70-991c02d47aec
相同的UID:66eb72f5-a3de-4941-8a64-6dad773f0ffb的线程ID发现:1093179712,计数器:211449,先前计数器:211448,ID:66eb72f5-a3de-4941-8a64-6dad773f0ffb
相同的UID:8bccb459-1e70-4920-8486-6b0c5dcb3992在线程ID发现:1093179712,计数器:212972,先前计数器:212971,ID:8bccb459-1e70-4920-8486-6b0c5dcb3992
相同的UID:在线程ID发现bb8109e3-6529-4122-A015-a9746900f692:1093179712,计数器:239296,先前计数器:239295,ID:bb8109e3-6529-4122-A015-a9746900f692
相同的UID:a02ea282-b49b-4e4f-98a3-01406824c888的线程ID发现:1103669568,计数器:338582,先前计数器:338581,ID:a02ea282-b49b-4e4f-98a3-01406824c888
相同的UID:在线程ID发现8bc848d7-bbe9-405c-9ef3-4d5ec312aa5e:1093179712,计数器:472035,先前计数器:472010,ID:8bc848d7-bbe9-405c-9ef3-4d5ec312aa5e
相同的UID:在线程ID发现d3d8e09f-c410-4ce0-9a75-2a0c363db89c:1093179712,计数器:531441,先前计数器:531440,ID:d3d8e09f-c410-4ce0-9a75-2a0c363db89c
相同的UID:在线程ID发现3130184f-345e-4d1c-BB01-d481eec29704:1093179712,计数器:548770,先前计数器:548769,ID:3130184f-345e-4d1c-BB01-d481eec29704
相同的UID:在线程ID发现29572641-2487-400a-926f-9bbf7ca176b4:1093179712,计数器:710813,先前计数器:710811,ID:29572641-2487-400a-926f-9bbf7ca176b4
相同的UID:在线程ID发现36b3567d-5f06-4c72-A395-e6f6ce056c6b:1093179712,计数器:728598,先前计数器:728597,ID:36b3567d-5f06-4c72-A395-e6f6ce056c6b
相同的UID:在线程ID发现3290cb7e-2535-43bc-b53c-71ac0bc4fca1:1103669568,计数器:846883,先前计数器:846881,ID:3290cb7e-2535-43bc-b53c-71ac0bc4fca1
相同的UID:在线程ID发现59137657-2b2a-473e-b12c-1890d6058ca2:1093179712,计数器:814812,先前计数器:814810,ID:59137657-2b2a-473e-b12c-1890d6058ca2
这是一个<一个href=\"http://stackoverflow.com/questions/5158990/concerning-raii-how-to-$p$pvent-errors-caused-by-accidentally-creating-a-temporar\">common <一href=\"http://stackoverflow.com/questions/914861/disallowing-creation-of-the-temporary-objects\">error使用RAII锁时:你忘了给你的锁的名称的该行
的boost ::互斥:: scoped_lock中(m_mRandomGen);
所以也没锁的所有东西。将其更改为
的boost ::互斥:: scoped_lock的LK(m_mRandonGen); //注意互斥名错字
编辑:到底发生了什么:有,尽管互斥名错字没有编译器错误,因为声明
键入(名);
是相同的
键入名称;
如果该名称尚未之前声明。换句话说,你已经默认构造一个新的的scoped_lock
名为 m_mRandomGen
,不与互斥有关。
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
boost::mutex::scoped_lock(m_mRandomGen);
so it didn't lock anything at all. Change it to
boost::mutex::scoped_lock lk(m_mRandonGen); // note the typo in mutex name
EDIT: what really happened: There was no compiler error despite the typo in the mutex name because the declaration
type(name);
is the same as
type name;
if the name has not been declared before. In other words, you've default-constructed a new scoped_lock
called m_mRandomGen
, not associated with a mutex.
这篇关于提高:: ::的UUID和random_generator独特多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!