【问题标题】:thread-safe usage of std::mapstd::map 的线程安全使用
【发布时间】:2015-01-26 02:51:55
【问题描述】:

我有一个std::map<int, object*>,我需要从不同的线程访问(读取和写入)它。当然,我可以只使用一个临界区进行读写,但这会对性能产生巨大影响,因为我有很多 find() 调用(每秒几千个)和更少的写入(通常,一个在创建和销毁线程时插入和一个擦除)。

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

谁能给我一个例子或解释如何做到这一点?谢谢!

【问题讨论】:

标签: c++ multithreading visual-studio-2008 stl


【解决方案1】:

您可以创建一个类来包装您的 std::map 并使用互斥锁锁定写入/读取功能。使用互斥体结构作为此类的成员,并根据每个函数适当地锁定/解锁。

Windows API 有一些mutex functions 向系统注册互斥句柄。句柄充当 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 );
        }
};

【讨论】:

    【解决方案2】:

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

    如果没有,你将不得不自己做(阅读这个other thread 在 SO)。你也可以使用 MS SRW 锁,正如T.C. 在他的评论中所说的那样(见there)。

    现在,假设您的课程 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_unlocked()
    • 一个公共的:operation(),它使用shared_mutex

    【讨论】:

      猜你喜欢
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 2010-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多