开发者

Is the c++ mutable keyword bad for threads?

From my understanding of the mutable keyword, one of its primary uses is caching data and computing them when needed. Since they can change (even though they are const) wouldnt it be unsafe or pointless to use them? The caching part modifies the data so there would need to be a lock and from my understanding when you write for multithreads the data should NEVER change and copies should be made and开发者_Go百科 returned/chained together.

So is it pointless or bad to use C++'s mutable keyword?


So is it pointless or bad to use C++'s mutable keyword?

No; the mutable keyword is A Good Thing. mutable can be used to separate the observable state of an object from the internal contents of the object.

With the "cached data" example that you describe (a very common use of mutable), it allows the class to perform optimizations "under the covers" that don't actually modify the observable state.

With respect to accessing an object from multiple threads, yes, you have to be careful. In general, if a class is designed to be accessed from multiple threads and it has mutable variables, it should synchronize modification of those variables internally. Note, however, that the problem is really more a conceptual one. It's easy to reason that:

  1. All of my threads only call const member functions on this shared object
  2. Const member functions do not modify the object on which they are called
  3. If an object is not modified, I don't need to synchronize access to it
  4. Therefore, I don't need to synchronize access to this object

This argument is wrong because (2) is false: const member functions can indeed modify mutable data members. The problem is that it's really, really easy to think that this argument is right.

The solution to this problem isn't easy: effectively, you just have to be extremely careful when writing multithreaded code and be absolutely certain that you understand either how objects being shared between threads are implemented or what concurrency guarantees they give.


On the opposite end, most of my multithreaded code requires the use of the mutable keyword:

class object {
   type m_data;
   mutable mutex m_mutex;
public:
   void set( type const & value ) {
      scoped_lock lock( m_mutex );
      m_data = value;
   }
   type get() const {
      scoped_lock lock( m_mutex );
      return m_data;
   }
};

The fact that the get method does not modify the state of the object is declared by means of the const keyword. But without the mutable modifier applied to the declaration of the mutex attribute, the code would not be able to lock or release the mutex --both operations clearly modify the mutex, even if they do not modify the object.

You can even make the data attribute mutable if it can be lazily evaluated and the cost is high, as long as you do lock the object. This is the cache usage that you refer to in the question.

The mutable modifier is not a problem with multithreaded code, only when you try to do lock-less multithreading. And as with all lock-less programming, you must be very careful with what you do, regardless of const or mutable. You can write perfectly unsafe multithreaded code that calls const methods on objects with no mutable attributes. The simple example would be removing the mutex from the previous code and having N threads perform only get()s while another thread performs set()s. The fact that get() is const is no guarantee that you will not get invalid results if another thread is modifying.


No, the mutable keyword is so that you can have fields inside an object that can change even when the object is const, such as for metadata that isn't part of an object's properties but its management (such as counters, etc.). It has nothing to do with threading.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜