8

シングル スレッドで乱数を生成すると、生成される 4M uuid に重複はありませんが、1M ごとに 2 つのスレッドで生成すると、およそ 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、カウンター: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: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 で見つかりました

4

1 に答える 1

12

これは、 RAII ロックを使用しているときによく あるエラーです。行でロックに名前を付けるのを忘れました

      boost::mutex::scoped_lock(m_mRandomGen);

したがって、何もロックしませんでした。に変更します

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

編集:実際に何が起こったのか:ミューテックス名のタイプミスにもかかわらず、コンパイラエラーはありませんでした。

type(name);

と同じです

type name;

名前が以前に宣言されていない場合。つまり、 mutex に関連付けられていないscoped_lockという新しい名前をデフォルトで作成しました。m_mRandomGen

于 2011-06-01T17:28:59.653 に答える