【问题标题】:boost::uuids::random_generator and uniqueness with multiple threadsboost::uuids::random_generator 和多线程的唯一性
【发布时间】:2011-09-06 11:33:36
【问题描述】:

当我用单线程生成随机数时,生成的 4M uuid 中没有重复,但如果我用两个线程生成,每个 1M,我会看到大约 16-20 个重复。可能是什么原因?

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;
}

下面是日志。

重复 uid:9f4bfa5c-8e41-4012-ba3e-0b3e631834dc 在线程 id: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, counter:170570,较早的 counter:170568, id:7a999ce7-0936-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, counter:211449,较早的 counter:211448, id:66eb72f5-a3de-4941-8a64-6dad773f0ffb 中找到 重复的 uid:8bccb459-1e70-4920-8486-6b0c5dcb3992 在线程 id:1093179712,计数器:212972,早期计数器:212971,id:8bccb459-1e70-4920-8486-6b0c5dcb3992 中找到 重复的 uid:bb8109e3-6529-4122-a015-a9746900f692 在线程 id: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:8bc848d7-bbe9-405c-9ef3-4d5ec312aa5e 在线程 id:1093179712,计数器:472035,早期计数器:472010,id:8bc848d7-bbe9-405c-9ef3-4d5ec312aa5e 中找到 重复的 uid:d3d8e09f-c410-4ce0-9a75-2a0c363db89c 在线程 id:1093179712,计数器:531441,早期计数器:531440,id:d3d8e09f-c410-4ce0-9a75-2a0c363db89c 重复的 uid:3130184f-345e-4d1c-bb01-d481eec29704 在线程 id:1093179712,计数器:548770,早期计数器:548769,id:3130184f-345e-4d1c-bb01-d481eec29704 中找到 重复的 uid:29572641-2487-400a-926f-9bbf7ca176b4 在线程 id:1093179712,计数器:710813,早期计数器:710811,id:29572641-2487-400a-926f-9bbf7ca176b4 中找到 重复的 uid:36b3567d-5f06-4c72-a395-e6f6ce056c6b 在线程 id:1093179712,计数器:728598,早期计数器:728597,id:36b3567d-5f06-4c72-a395-e6f6ce056c6b 中找到 重复的 uid:3290cb7e-2535-43bc-b53c-71ac0bc4fca1 在线程 id:1103669568,计数器:846883,早期计数器:846881,id:3290cb7e-2535-43bc-b53c-71ac0bc4fca1 中找到 重复的 uid:59137657-2b2a-473e-b12c-1890d6058ca2 在线程 id:1093179712,计数器:814812,早期计数器:814810,id:59137657-2b2a-473e-b12c-1890d6058ca2 中找到

【问题讨论】:

    标签: c++ boost thread-safety boost-uuid


    【解决方案1】:

    这是commonerror 使用 RAII 锁时:您忘记在行中为您的锁指定一个名称

          boost::mutex::scoped_lock(m_mRandomGen);
    

    所以它根本没有锁定任何东西。改成

          boost::mutex::scoped_lock lk(m_mRandonGen); // note the typo in mutex name
    

    编辑:真正发生的事情:尽管互斥锁名称中有错字,但没有编译器错误,因为声明

    type(name);
    

    一样
    type name;
    

    如果名称之前没有声明过。换句话说,您已经默认构造了一个名为 m_mRandomGen 的新 scoped_lock,它与互斥体无关。

    【讨论】:

    • 谢谢。我很惊讶它没有给出错误。事实上,m_mRandomGen 没有使用互斥锁。有一个错字,它是 m_mRandonGen。不是 m,而是 n。有编译错误:(
    • 微妙。也许您可以添加原始语句所做的。事实上,我相信它确实锁定了 m_mRandomGen。只是没有达到预期的持续时间?
    • @sehe 添加了真实情况(没有 m_mRandomGen 可以锁定!)
    • 如果定义了 m_mRandomGen 互斥锁,你是说 boost::mutex::scoped_lock(m_mRandomGen) 与 boost::mutex::scoped_lock guard(m_mRandomGen) 相同吗?
    • @rjoshi 不,它与boost::mutex::scoped_lock guard; 相同,不涉及互斥体。
    猜你喜欢
    • 2013-09-24
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 2021-11-06
    相关资源
    最近更新 更多