在多线程环境中从STL Map读取/写入

som*_*one 1 c++ multithreading stl pthreads

问题:我需要编写一个函数,该函数从地图返回输入键的值.如果函数找不到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;
}
Run Code Online (Sandbox Code Playgroud)

这个功能线程安全吗?两个或多个线程是否有可能在写锁定时排队并从数据库中查询相同的密钥?如果是,我该如何避免这种情况?

Jam*_*lis 7

此函数不是线程安全的,因为它会导致未定义的行为.当您尝试获取写锁定时,您已经拥有读锁定.从以下文档pthread_rwlock_wrlock:

如果调用线程在调用[to 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
Run Code Online (Sandbox Code Playgroud)

[如果你使用某种类型的东西lock_guard,你不必担心在你返回时释放持有的锁]