Smart Pointer Thread Safety

by Dejan Jelovic

What does it mean when we say that a smart pointer is thread-safe? Fundamentally, it means this:

You can pass a smart pointer from one thread to another, and the two threads are free to use their smart pointers just as they were native pointers. They can copy them, assign them, and do whatever they want with them, and the smart pointer will not get you into trouble.

It doesn't mean that you can do whatever you want with the object that the smart pointer is pointing to. If it is used by two or more threads, then it is a shared resource. That means that you must implement your own protocol for using this object. In this, a smart pointer is no different from a native pointer.

How to Get into Trouble

There are two ways you can get into trouble using smart pointers and threads.

The first is to have a "strong" smart pointer in one thread, and a weak pointer in another. Then if the second thread executes something like:

weakPtr->someFunction ();

while the pointer in the first thread gets destroyed, the whole sequence can happen like this:

  1. In thread 2, the weak pointer gets dereferenced, and T* is returned.
  2. In thread 1, the strong pointer gets destroyed, and destructs the object.
  3. In thread 2, the weak pointer calls someFunction using the now invalid  pointer.

This is basically a non-issue with real-world code. A weak pointer never lives alone on a thread. It is always there together with the strong pointers, since the only purpose of weak pointers is to help resolve circular references with strong pointers*. Nonetheless, you should be aware that it can happen in theory.

The other way to get into trouble is to have a smart pointer that is read by one thread and written to by another. When we say that a smart pointer is thread-safe, we mean that it doesn't get in the way of accessing a shared resource, and that different threads that own smart pointers to an object are free to do with them whatever they like.

But if you decide to use a smart pointer as a shared resource itself, then you are responsible for managing the protocol using which they are accessed.

(In this, smart pointers are no different than native pointers. If you have a thread writing to a native pointer while another one writes to it, it is easy to read a corrupt value.)

 

* In garbage collected languages a weak pointer is often used to differentiate between external and internal ownership. With reference counted pointers the same effect is achieved using a level of indirection.  

 

 

Read more...


Content of this site is © Dejan Jelovic. All rights reserved.