加锁

一般来说我们对于一些延迟初始化的资源操作如下:

std::shared_ptr<some_resource> resource_ptr;
void foo() 
{
  if (!resource_ptr) {
    resource_ptr.reset(new some_resources); // 及时初始化
  }
  resource_ptr->do_sth();
}

如果有多个线程执行foo函数,那么可能会出现线程不安全的情况。

所以可以这样改写,利用互斥实现线程安全的延迟初始化

std::shared_ptr<some_resource> resource_ptr;
std::mutex resource_mtx;
void foo()
{
    std::unique_lock<std::mutex> lock(resource_mtx);
    if (!resource_ptr) {
        resource_ptr.reset(new some_resources); // 及时初始化
    }
    lock.unlock();
    resource_ptr->do_sth();
}

std::call_once可以保证所有线程共同调用时的线程安全且唯一完成。

我们来改写一下上面的代码:

std::shared_ptr<some_resource> resource_ptr;
std::once_flag resource_flag;
void init_resouce() {
    resource_ptr.reset(new some_resources); // 及时初始化
}
void foo()
{
    std::call_once(resource_flag, init_resouce);
    resource_ptr->do_sth();
}

class X {
private:
    connection_info connection_details;
    connection_handle connection;
    std::once_flag connection_init_flag;
    void open_connection() {
        connection = connection_manager.open(connection_details);
    }
public:
    X(connection_info const& connection_details_) : connection_details(connection_details_) {}
    void send_data(data_packet const& data) {
        std::call_once(connection_init_flag, &X::open_connection, this);
        connection.send_data(data);
    }
    data_packet receive_data() {
        std::call_once(connection_init_flag, &X::open_connection, this);
        return connection.receive_data();
    }
};

C++11之后可以使用static变量进行声明。保证控制流程中初始化只会在某一个线程中单独发生