[英]Heap Corruption while Reading/Writing custom Map in multithreaded application
[英]Reading/Writing from STL Map in multithreaded environment
问题:我需要编写一个函数,该函数从映射返回输入键的值。 如果函数在map中找不到值,它将从数据库中获取该值,写入map以供将来使用并返回相同值。 可以有多个线程调用此函数。
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
{
pthread_rwlock_wrlock(&rwlock); // write lock
//fetch value from data base
//if successful, add to the map
m[key] = "missing data";
result = "missing data";
pthread_rwlock_unlock(&rwlock); // unlock write lock
}
pthread_rwlock_unlock(&rwlock); // unlock read lock
return result;
}
这个函数线程安全吗? 两个或更多线程是否有可能在写锁上排队并从数据库查询同一密钥? 如果是,如何避免这种情况?
此函数不是线程安全的,因为它会导致未定义的行为。 当您尝试获取写锁时,您已经持有一个读锁。 从pthread_rwlock_wrlock
的文档中:
如果在调用[
pthread_rwlock_wrlock
]时调用线程持有读写锁(无论是读锁还是写锁),则结果不确定。
此解决方案也不是异常安全的。 如果在持有该锁的同时抛出异常,则该锁将不会被释放,并且您的应用程序无疑会死锁。 您应该使用C ++线程库(Boost.Thread,OpenThreads,just :: thread或类似的东西),该库提供面向C ++的设计,支持诸如scoped_lock
(或lock_guard
)之类的东西。
为了使算法正确,您需要遵循以下原则:
obtain read lock
attempt to find object
if object exists
return object
else
release read lock
obtain write lock
if object exists
return object
else
insert object
return object
[如果使用某种lock_guard
,则不必担心在返回时释放持有的锁]
实施不正确。 担心保持死锁状态,您在持有读锁的同时不能使用写锁。 在我的Linux机器上的pthread_rwlock_wrlock手册页中:
pthread_rwlock_wrlock()函数应将写锁应用于rwlock引用的读写锁。 如果没有其他线程(读取器或写入器)持有读写锁rwlock,则调用线程将获得写入锁。 否则,线程将阻塞直到可以获取锁为止。 如果在调用时它拥有读写锁(无论是读锁还是写锁),则调用线程可能会死锁。
此外,您应该检查调用的返回值...例如,同时读取器的数量有一个实现定义的限制。
还有一些异常安全性的常见问题...考虑一下示波器保护或try / catch块。
获得写锁定后,您可以修复它以再次寻找该值。 这应该足以解决您正在描述的问题。 就像是:
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 {
//if successful, add to the map
m[key] = "missing data";
result = "missing data";
}
}
pthread_rwlock_unlock(&rwlock); // unlock read/write lock
return result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.