-1

我在多线程环境中的映射中具有读取、写入和删除三个功能。那么它们工作正常吗?或者它们会产生死锁或我想在多线程程序中从映射中读取、写入和删除的任何其他类型的错误。

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

2 回答 2

0

只要您的代码没有其他干扰并且不引发异常的互斥锁,它看起来还可以并且不会产生任何死锁。

当您将 C 风格的代码与 C++ 混合时,异常是您最大的敌人。我建议您查看 C++11std::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;
  }
}
于 2013-03-08T05:47:33.797 回答
0

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

  1. 例如删除数据;如果你确实找到了读锁下的记录,你在用它做什么?不删?您的写入功能也是如此。
  2. 为什么要在写入和删除功能中使用读锁?为什么不立即使用写锁呢?
  3. 在阅读中,你为什么要写锁呢?

根据我的伪代码应该是

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

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

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

你不能只用一把锁就出现死锁。您至少需要两个锁和一个特定的模式才能发生死锁。例如

螺纹 1 锁(A) 锁(B)

螺纹 2 锁(B) 锁(A)

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

如果您想变得更奇特,并担心其他潜在问题,那么您可以担心优先级反转。我说的是异国情调,因为在大多数情况下,您甚至不必考虑它。

于 2013-03-08T05:48:33.467 回答