在多线程环境中读取/写入STL 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;
}
这个函数线程安全吗?两个或多个线程是否可以在写锁上排队并从数据库中查询相同的键?如果是,我该如何避免这种情况?
Problem: I need to write a function which returns a value for a input key from a map. If function can't found the value in map it will fetch the value from database, write into map for future use and return the same. There can be multiple threads calling this function.
I am thinking on this line:
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;
}
Is this function thread safe? Isn't it possible for two or more threads to queue up on write lock and query the same key from database? If yes, how can I avoid that scenario?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
此函数不是线程安全的,因为它会导致未定义的行为。当您尝试获取写锁时,您已经持有读锁。来自
pthread_rwlock_wrlock
的文档:该解决方案也不是异常安全的。如果在持有锁时抛出异常,锁将不会被释放,您的应用程序无疑会死锁。您应该使用 C++ 线程库(Boost.Thread、OpenThreads、just::thread 或类似的东西),它提供面向 C++ 的设计,支持诸如
scoped_lock
(或lock_guard)。
至于使算法正确,您需要以下内容:
[如果您使用某种
lock_guard
,则无需担心返回时释放持有的锁]This function is not thread-safe because it results in undefined behavior. When you attempt to obtain the write lock, you already hold a read lock. From the documentation for
pthread_rwlock_wrlock
:This solution is also not exception-safe. If an exception is thrown while the lock is held, the lock will not be released and your application will undoubtedly deadlock. You should use a C++ threading library (Boost.Thread, OpenThreads, just::thread, or something similar) that provides a C++-oriented design supporting things like
scoped_lock
(orlock_guard
).As for making the algorithm correct, you need something along the lines of:
[If you use some sort of
lock_guard
, you don't need to worry about releasing held locks when you return]没有正确实施。不能在保持读锁的同时获取写锁,以免发生死锁。来自我的 Linux 机器上 pthread_rwlock_wrlock 的手册页:
此外,您应该检查调用的返回值...例如,对同时读取器的数量存在实现定义的限制。
还有异常安全的常见问题......考虑范围保护或 try/catch 块。
Not properly implemented. You can't take the write lock while still holding the read lock, for fear of deadlock. From the man page for pthread_rwlock_wrlock on my Linux box:
Further, you should check the return value of the calls... for example, there's an implementation-defined limit to the number of simultaneous readers.
There are also the usual issues with exception safety... consider a scope guard or try/catch block.
一旦获得写锁,您可以修复它并再次查找该值。这应该足以解决您所描述的问题。像这样的东西:
You might fix it looking for the value again once you have acquired the write lock. That should be enough to fix the problem you are describing. Something like: