C++ std::map的线程安全使用

C++ std::map的线程安全使用,c++,multithreading,visual-studio-2008,stl,C++,Multithreading,Visual Studio 2008,Stl,我有一个std::map,我需要从不同的线程访问它(读写)。当然,我可以只使用一个关键部分进行读写操作,但这将对性能产生巨大影响,因为我有很多find()调用(每秒数千次)和更少的写操作(通常,在创建和销毁线程时一次插入和一次擦除) 因此,我需要使用CriticalSection进行写入,并且在读取之前只检查另一个线程是否正在执行写入操作。但是怎么做呢? 我找到了C++11和boost的解决方案,但我使用的是Visual Studio 2008(因为兼容性问题) 有人能给我举个例子或解释一下怎么

我有一个
std::map
,我需要从不同的线程访问它(读写)。当然,我可以只使用一个关键部分进行读写操作,但这将对性能产生巨大影响,因为我有很多
find()
调用(每秒数千次)和更少的写操作(通常,在创建和销毁线程时一次插入和一次擦除)

因此,我需要使用
CriticalSection
进行写入,并且在读取之前只检查另一个线程是否正在执行写入操作。但是怎么做呢? 我找到了C++11和boost的解决方案,但我使用的是Visual Studio 2008(因为兼容性问题)


有人能给我举个例子或解释一下怎么做吗?谢谢

您可以创建一个类来包装std::map并用互斥锁锁定写/读函数。将互斥结构用作此类的成员,并根据函数的不同适当锁定/解锁

Windows API需要在系统中注册互斥句柄。句柄充当Windows识别互斥体并检查它是否正在等待的一种方式

下面是一个简单的互斥类,让您开始使用一些Windows API调用

class MyMutex {

    private:
        HANDLE m_hMutex; 

    public:
        MyMutex()
        {
            m_hMutex = CreateMutex(NULL, FALSE, NULL);
        }

        ~MyMutex()
        {
            CloseHandle(m_hMutex);
        }

        void Lock()
        {
            BOOL test = WaitForSingleObject( m_hMutex, INFINITE );
        }

        void UnLock() 
        {
            ReleaseMutex( m_hMutex );
        }
};

您需要的是一个多读卡器/单写卡器锁定系统。不幸的是,这没有内置类型(在C++14之前)。如果你可以使用boost,那么你可以使用boost的

如果没有,你就得自己做(请阅读本文)。您也可以使用MS SRW lock,如在其评论中所述(请参阅)

现在,假设您的类
shared_mutex
定义良好且可用。您只需添加一个
shared_mutex
对象作为要保护的类的属性。我建议您在类中保持完全无锁方法,并在其周围添加包装器,如下所示:

class Whatever;
class MyClass {
    boost::shared_mutex mutex;
    Whatever find_unlocked() {
        whatever blob_blob;
        blob_blob = do_whatever_work_find_does();
        return blob_blob;
    }
    void write_smth_unlocked() {
        do_something_that_needs_writing_to_MyClass();
    }
public:
    Whatever find() {
        Whatever blob;
        mutex.lock_shared(); // Locks for reading (shared ownership on the mutex)
        blob = find_unlocked();
        mutex.unlock_shared();
        return blob;
    }
    void write_smth() {
        mutex.lock(); // Locks for writing (exclusive ownership on the mutex)
        write_smth_unlocked();
        mutex.unlock();
    }
};
这样做将使您能够重用在类的新特性中定义的操作,同时仍然能够通过锁定系统保护整个新操作

最后,对于您定义的任何操作,您将有两种方法:

  • 私有(或受保护)方法:
    operation\u unlocked()
  • 一个公共的:
    operation()
    ,它使用
    共享的\u互斥体

Vista或更高版本的Windows API中也有读写器锁定。