用C++设计线程安全变量类

Design thread safe variable class in C++

本文关键字:安全 变量 线程 C++      更新时间:2023-10-16

我遇到了一个常见的问题(在这里发布了几个变体),一个进程运行多个线程,每个线程都可以读取或写入一组公共变量(为了简单起见,假设它是单个变量)。

每个变量都应该防止并行写入,并允许并行读取。

我已经看到了几个解决方案,并决定专注于下面一个使用保护(在这个链接中提到)

然而,我无法理解以下原则:

  1. MutexGuard类:它不应该实现为singleton吗。否则,每个线程将创建新的互斥体,而不是等待单个公共互斥体。

  2. 如果类MutexGuard不是singleTon,那么至少m_Mutex应该是静态的,这样它将在该类的所有实例之间共享。

  3. 为什么函数1和函数2被定义为静态。这样就可以在没有实例上下文的情况下调用它(类只是名称空间),并且可能缺少m_SharedVar的值。

  4. 有什么简单的方法可以修改多读卡器/单写器锁的实现吗?在这种情况下,我应该只更改互斥对象类型吗?

    class MutexGuard {
        MutexType & m_Mutex; 
        public:
        inline MutexGuard(MutexType & mutex) : m_Mutex(mutex) { 
            m_Mutex.lock();
        };
        inline ~MutexGuard() { 
            m_Mutex.unlock();
        };
    }
    class TestClass {
        MutexType m_Mutex;
        double m_SharedVar;
        public:
        TestClass() : m_SharedVar(4.0) { }
        static void Function1() {
            MutexGuard scopedLock(m_Mutex); //lock the mutex
            m_SharedVar+= 2345;
           //mutex automatically unlocked
        }
        static void Function2() {
            MutexGuard scopedLock(m_Mutex); //lock the mutex
            m_SharedVar*= 234;
            throw std::runtime_error("Mutex automatically unlocked");
       }
    }
    

我认为这里的问题是TestClass。正如@TonyD正确指出的那样,MutexGuard的实现不应该绑定到singleton,除非它是明确必要的。CCD_ 3的意图是执行CCD_;以自动方式为调用方指定互斥对象的unlock()。因此MutexGuard的调用者不必显式地lock()unlock()

现在,TestClass负责保护互斥对象不受多重访问的影响。通常,如果每个函数都锁定了与类实例共享的互斥体,那么使用TestClass函数的所有工作线程都将被自动保护。同样,它是具体实施的。所有实例可以有一个静态互斥,也可以有多个针对不同共享资源的互斥。

现在来谈谈你的问题

有什么简单的方法可以修改多阅读器的实现吗/单个写入程序锁定?在这种情况下,我应该只更改互斥对象类型吗?

你必须明白,多个读者/一篇文章是一个神话。它不能保证并行性。这只是意味着,锁定/解锁会根据需要更快。即,除非有人在写日期,否则多个读取器可以读取数据(假设值没有更改)。在这种情况下,您可能想要实现reader-writer锁。

我的教授总是把mutex锁称为胖锁。它并没有真正区分读/写,并且总是有恒定的锁定时间,无论您打算在共享资源上做什么工作。

欲了解更多信息,请参阅这篇stackoverflow帖子。或者,您也可以使用现成的BOOST读写器锁。