我在多线程环境中有三个用于读取,写入和删除的功能。 那么它们是否正常工作?或者它们会造成死锁或任何其他类型的错误 我想在多线程程序中从地图中读取,写入和删除。
//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;
}
答案 0 :(得分:0)
看起来没问题,只要您的代码没有干扰且不会抛出异常的其他互斥锁,就不会造成任何死锁。
当你将C风格的代码与C ++混合时,异常是你最大的敌人。我建议您查看C ++ 11的std::mutex
和std::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)
您的代码几乎没有问题;所以它在我看来。
根据我的伪代码应该是
读 - 采取读锁 - 找。存储结果 - 找到或未找到。 - 释放锁定 - 返回
写入 - 采取写锁定 - 写。决定是否覆盖现有密钥。如果没有覆盖你会返回什么?大多数标准实现都设置为覆盖。 - 释放锁定 - 返回
你的一般方法很好 - 没问题。
只有一个锁,你不能有死锁。您需要至少两个锁和一个特定的死锁模式。 e.g。
线程1 锁(A) 锁(B)
线程2 锁(B) 锁(A)
如果线程1在第一次锁定调用之后立即换出并且线程2启动,则上述情况可能会导致死锁。
如果你想要更加异国情调,并担心其他潜在的问题,那么,例如你可以担心优先级倒置。我说异国情调,因为在大多数情况下你甚至不必考虑它。