2016-11-23 107 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毫秒相比,大大無關緊要。

保存這些鳥。