2016-11-23 86 views
0

我已阅读过有关在任意CPU上使用C++可能不安全的重复检查的文章。我不太确定我的代码是否绝对安全。 类数据库表示数据库文件,并在需要时动态创建连接。 Database :: GetConnection可以同时从不同的线程中调用。如果代码不是绝对安全的,我该如何修改代码。谢谢。这段代码是否是线程安全的C++

#include <mutex> 
#include "sqlite3.h" 

class Connection 
{ 
private: 
    sqlite3* _handle; 
    std::string _path; 
public: 
    Connection(const std::string& path) : _path(path) { 
     sqlite3_open(_path.c_str(), &_handle); 
     // some other initialization work.. 
    } 
} 

class Database 
{ 
private: 
    typedef enum 
    { 
     Void, 
     Connected, 
     // some other status... 
    } Status; 

    std::string _path; 
    std::mutex _mutex; 
    Status _status; 
    Connection* _connection; 

    void OpenDatabase() 
    { 
     _connection = new Connection(_path); 
     _status = Connected; 
    } 
public: 
    Connection* GetConnection() 
    { 
     if (_status == Connected) 
      return _connection; 

     std::lock_guard<std::mutex> guard(_mutex); 
     if (_status != Connected) 
      OpenDatabase(); 
     return _connection; 
    } 
public: 
    Database(const std::string& path) : _path(path), _status(Void) {}; 
}; 
+2

权威答案的信息不足,但看起来像这不是线程安全的。对我来说很明显,'_connection'和'_status'只能在保护互斥体上锁定时才能访问。但是,情况显然不是这样。 –

+4

你不守护'_status',你为什么认为它是安全的? – Tas

+0

我会尽管OpenDatabse返回连接,而不是它在类变量上运行。也许你需要的是一个单身人士? - http://stackoverflow.com/a/1008289/429476 –

回答

1

为了提高效率......是足够安全

你正在处理一个数据库,效率是没有实际意义和足够安全是你

足够的意味着允许的不确定性水平。 好吗?

发生了什么,在那0.001%的几率它是不是足够安全?软件崩溃了吗?硬件爆炸了吗?鸟儿会不会从天而降?

如果您OpenDatabase功能被锁定在其他地方你Database类,那么有什么错除去第一检查并留下您的GetConnection功能像这样:

Connection* GetConnection() 
{ 
    std::lock_guard<std::mutex> guard(_mutex); 
    if (_status != Connected) 
     OpenDatabase(); 
    return _connection; 
} 

你正在处理一个数据库,所以你的CPU创建和存储std::lock_guard并锁定/解锁_mutex对象需要几毫秒的时间,然后执行一个简单的布尔检查,与建立数据库连接和事务状态的100毫秒相比,大大无关紧要。

保存这些鸟。