As already stated many times, data races are situations programmers try to avoid at all costs. In the previous chapter, we discussed a deadlock and ways to avoid it. The last example that we used in the previous chapter was making a thread-safe singleton pattern. Let's suppose we use a class for creating database connections (a classic example).
Here's a simple implementation of the pattern that tracks down the connections to the database. Keeping a separate connection each time we need access to the database is not a good practice. Instead, we reuse the existing connection for querying the database from different parts of the program:
namespace Db {
class ConnectionManager
{
public:
static std::shared_ptr<ConnectionManager> get_instance()
{
if (instance_ == nullptr) {
instance_.reset(new ConnectionManager());
...