简体   繁体   中英

Design thread safe variable class in C++

I've got a common problem (that was posted here in several variations) of a process running multiple threads that each may read or write to a group of common variables (for the simplicity - say it's single variable).

Each variable should be protected against parallel write, and allow parallel read.

I've seen several solutions, and decided to focus on the following one that is using guards (mentioned in this link )

However, I Couldn't figure out the following principles:

  1. MutexGuard class : shouldn't it be implemented as singleton. otherwise, each thread will create new mutex, other than waiting on a single common mutex.

  2. if the class MutexGuard is not singleTon, so at least the m_Mutex should be static so it will be shared among all instances of this class.

  3. why are function1 and function2 defined as static. this way it can be called without the context of an instance (class is just namespace), and the value of m_SharedVar might be missing.

  4. 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 ?

     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"); } } 

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. ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM