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

时间:2016-04-07 06:16:32

标签: c++ multithreading thread-safety

我遇到了一个运行多个线程的进程的常见问题(在这里发布了几个版本),每个线程都可以读取或写入一组公共变量(为了简单起见 - 比如说' s单变量)。

应保护每个变量不受并行写入的影响,并允许并行读取。

我已经看过几个解决方案,并决定专注于下一个使用警卫的人(在此link中提到)

但是,我无法弄清楚以下原则:

  1. MutexGuard类:不应该以单例形式实现。否则,每个线程将创建新的互斥锁,而不是等待单个常见的互斥锁。

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

  3. 为什么function1和function2被定义为static。这样就可以在没有实例上下文的情况下调用它(类只是名称空间),并且可能缺少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");
       }
    }
    

1 个答案:

答案 0 :(得分:2)

I think the problem here is the TestClass. As rightly pointed by @TonyD, the implementation of MutexGuard shouldn't be bound to singleton unless it is explicitly necessary. The intention of MutexGuard is to perform lock() & unlock() of the given mutex in automatic way, for the caller. So the caller of MutexGuard doesn't have to explicitly lock() or unlock().

Now it becomes the responsibility of TestClass to guard the mutex from multiple access. Typically all the worker threads that uses the functions of the TestClass will be automatically guarded if each function is locking the mutex that is shared with the instance of the class. Again it is implementation specific. There can be one static mutex for all the instances or there can multiple mutexes aimed for different shared resources etc.

Now coming to your question of

is there any easy way to modify the implementation for multi-readers / single writer lock ? should i only change the mutex type in this case ?

You will have to understand that, multiple readers / single write is a myth. It doesn't guarantee parallelism. It only means that, the locking / unlocking gets quicker based on need basis. i.e Unless some is writing the date, multiple readers can read the data ( assuming that the value is not changed ). In such case, you might want to implement something known as reader-writer lock.

My professor always term mutex locks as fat-locks. It doesn't really discriminate between a read / write and always has constant locking time irrespective of the work that you intend to do on the shared resource.

For more info, please refer to this stackoverflow post. Or you can also use ready made BOOST reader-writer locks.