std :: map多线程程序中的读/写和删除

时间:2013-03-08 04:59:48

标签: c++ multithreading

我在多线程环境中有三个用于读取,写入和删除的功能。 那么它们是否正常工作?或者它们会造成死锁或任何其他类型的错误 我想在多线程程序中从地图中读取,写入和删除。

//Function for read 
string GetData (const int key)
{

    pthread_rwlock_rdlock(&rwlock); //read lock
    string result = "not found";
    my_map::const_iterator iter = m.find(key);
    if ( iter != m.end() )//found
    {
        result = iter->second;
    }
    else //missing
    {
        // change from read mode to write mode
        pthread_rwlock_unlock(&rwlock); // unlock read lock
        pthread_rwlock_wrlock(&rwlock); // write lock
        // Try again
        iter = m.find(key);
        if (iter != m.end()) {
            result = iter->second;
        }
        else
        {
        string = "";
        }
    }
    pthread_rwlock_unlock(&rwlock); // unlock read/write lock
    return result;
}

//Function for write
void SetData (const int key)
{

    pthread_rwlock_rdlock(&rwlock); //read lock
    string result = "not found";
    my_map::const_iterator iter = m.find(key);
    if ( iter != m.end() )//found
    {
        result = iter->second;
    }
    else //missing
    {
        // change from read mode to write mode
        pthread_rwlock_unlock(&rwlock); // unlock read lock
        pthread_rwlock_wrlock(&rwlock); // write lock
        // Try again
        iter = m.find(key);
        if (iter != m.end()) {
            result = iter->second;
        }
        else
        {
            m[key] = "missing data";
            result = "missing data";
        }
    }
    pthread_rwlock_unlock(&rwlock); // unlock read/write lock
    return result;
}
//Function for delete
//Function for write
void deleteData (const int key)
{
    pthread_rwlock_rdlock(&rwlock); //read lock
    string result = "not found";
    my_map::const_iterator iter = m.find(key);
    if ( iter != m.end() )//found
    {
        result = iter->second;
    }
    else //missing
    {
        // change from read mode to write mode
        pthread_rwlock_unlock(&rwlock); // unlock read lock
        pthread_rwlock_wrlock(&rwlock); // write lock
        // Try again
        iter = m.find(key);
        if (iter != m.end()) {
            my_map->erase(iter);
        }
        else
        {
        }
    }
    pthread_rwlock_unlock(&rwlock); // unlock read/write lock
    return result;
}

2 个答案:

答案 0 :(得分:0)

看起来没问题,只要您的代码没有干扰且不会抛出异常的其他互斥锁,就不会造成任何死锁。

当你将C风格的代码与C ++混合时,异常是你最大的敌人。我建议您查看C ++ 11的std::mutexstd::lock_guard,但您也可以手动修复它,请参阅下面的直接解决方案。有更优雅的方式,但重要的是以某种方式照顾它。

其他互斥锁怎么样?在您的示例中,如果它是用户定义的类型(不是某个标准容器),并且成员函数my_map等也会在内部锁定互斥锁,则它们可以隐藏在类型find中。在其他情况下(不在您的示例中),值也可能是UDT而不仅仅是int并使用互斥锁。

您的代码有一点奇怪:为什么GetData使用写锁定来锁定互斥锁?这似乎是多余和低效的。另外,对于其他函数,我只是立即获得写锁定并跳过一般的读取锁定。但是您可能想要分析那个,因为两者都可能是有效的用例,并且两者都可能具有潜在的性能优势。

此外,使用互斥锁时,如果可能,请始终将代码移动到锁定部分之外。也就是说,GetData应该是这样的:

string GetData (const int key)
{
  string result = "not found"; // moved before the lock
  pthread_rwlock_rdlock(&rwlock); //read lock
  try {
    my_map::const_iterator iter = m.find(key);
    if ( iter != m.end() )//found
    {
      result = iter->second;
    }
    pthread_rwlock_unlock(&rwlock); // unlock read/write lock
    return result;
  }
  catch( ... ) {
    pthread_rwlock_unlock(&rwlock); // unlock read/write lock
    throw;
  }
}

答案 1 :(得分:0)

您的代码几乎没有问题;所以它在我看来。

  1. e.g。 deleteData;如果你确实在读锁定下找到了记录,那你在做什么呢?不删除它?您的写入功能也是如此。
  2. 为什么要在写入和删除功能中使用读锁?为什么不马上拿写锁?
  3. 在阅读中你为什么还要写一个写锁?
  4. 根据我的伪代码应该是

    读 - 采取读锁 - 找。存储结果 - 找到或未找到。 - 释放锁定 - 返回

    写入 - 采取写锁定 - 写。决定是否覆盖现有密钥。如果没有覆盖你会返回什么?大多数标准实现都设置为覆盖。 - 释放锁定 - 返回

    你的一般方法很好 - 没问题。

    只有一个锁,你不能有死锁。您需要至少两个锁和一个特定的死锁模式。 e.g。

    线程1 锁(A) 锁(B)

    线程2 锁(B) 锁(A)

    如果线程1在第一次锁定调用之后立即换出并且线程2启动,则上述情况可能会导致死锁。

    如果你想要更加异国情调,并担心其他潜在的问题,那么,例如你可以担心优先级倒置。我说异国情调,因为在大多数情况下你甚至不必考虑它。